2009-02-09 33 views
5

Tôi muốn biết cách triển khai hạn chế sau: Một phương thức trong Dịch vụ Windows của tôi không được gọi lại trước khi cuộc gọi trước đó kết thúc. Phương thức được đề cập đến có một vài bảng cơ sở dữ liệu và điều quan trọng là quá trình này sẽ không được gọi lại trước khi nó kết thúc. Tôi có một cài đặt xác định tần suất dịch vụ của tôi sẽ kích hoạt và trong trường hợp bình thường, nó không bao giờ được kích hoạt trước khi cuộc gọi trước đó kết thúc (vì toàn bộ quá trình không mất quá vài phút và khoảng thời gian được đặt là 10 phút) đảm bảo đủ. Tôi đoán.Làm thế nào để hạn chế một cuộc gọi phương thức tại một thời điểm?

Cách triển khai tính năng này?

+0

Bạn có muốn bỏ qua các cuộc gọi tiếp theo hoặc xếp hàng đợi không? –

Trả lời

11

Bạn có thể sử dụng số named Mutex hoặc named Semaphor e để đảm bảo rằng chỉ một chủ sở hữu của Mutex/Semaphore đang thực hiện cùng một lúc. Như một người bình luận đã chỉ ra, hãy nhớ rằng bạn phải cẩn thận không từ bỏ một mutex hoặc thu thập/phát hành một semaphore không đúng cách.

+0

Tôi thích câu trả lời của bạn tốt hơn –

+0

Tôi muốn sử dụng semaphore có tên, không có rủi ro bị đột biến bị bỏ rơi vì vậy không cần phải giải quyết thêm khả năng gặp ngoại lệ hoặc phải suy nghĩ về quyền sở hữu. –

+0

+1 Peter Morris, tôi sẽ thêm một sự lo lắng về khả năng của một Semaphore tên, tuy nhiên, họ cũng có vấn đề với phát hành không đúng, vv – user7116

1

Vâng, nếu tất cả mã được bản địa hóa, bạn có thể đặt boolean và kiểm tra boolean trước khi thực thi phương thức, nếu không bạn có thể IPC và yêu cầu trạng thái trước khi thực thi.

4

Một cách sẽ được sử dụng khóa:

private readonly object myLock = new object(); 

private void MyMethod() 
{ 
    lock(myLock) 
    { 
     //code goes here 
    } 
} 

Điều này đảm bảo rằng phương pháp này không bao giờ có thể được chạy hơn một lần tại một thời điểm.

+0

đừng quên để làm cho myLock tĩnh - câu hỏi thực sự ngụ ý tình trạng multythreaded. –

+0

Tôi tin rằng đó thực sự là một tình huống đa tiến trình. – user7116

1

Một số lựa chọn thay thế:

  1. Bạn có thể đặt một tấm séc trong cuộc gọi để kiểm tra một số cờ hoặc gọi Monitor.TryEnter và trở về với một lỗi/không làm gì cả nếu âm tính.
  2. Bạn có thể xếp hàng cuộc gọi (nếu bạn cần phương thức này để thực hiện nhiều lần) và chỉ gọi khi Màn hình được báo hiệu.
  3. Nếu bạn không ngại chặn và phương pháp này nằm trên một chuỗi riêng biệt, bạn có thể tham gia chuỗi của phương thức bạn muốn đợi.

Tôi chắc chắn có những người khác.

0

Điều này nghe giống như quy trình làm việc nối tiếp ... Bạn đã cân nhắc sử dụng khung công việc chưa?

2

Tôi thứ hai đề xuất Mutex, nhưng bạn cũng có thể muốn xem xét các giao dịch. Quấn toàn bộ mã của bạn trong một giao dịch (điều này đòi hỏi một using System.Transactions):

using(TransactionScope scope = new TransactionScope()) 
{ 
    try 
    { 
     /* ... your current code here */ 
     scope.Complete(); 
    } 
    catch (Exception e) 
    { 
     /* Any appropriate error handling/logging here */ 
    } 
    finally 
    { 
    } 
} 

một TransactionScope tự động khóa tất cả các bảng liên quan. Bạn có thể giảm các hạn chế và cho phép các quy trình khác đọc, nhưng không ghi vào dữ liệu mà quy trình của bạn đang chạm vào. Bạn làm điều này bằng cách chuyển các tùy chọn cho hàm tạo TransactionsScope.

+0

Rất tiếc, tất cả tin nhắn đó không được gửi cho tôi lần đầu tiên, lỗi trong hệ thống? – rjzii

+0

Trục trặc khi nhập. Tôi đã bất ngờ gửi trả lời của tôi trước khi hoàn thành bài viết hoàn chỉnh. –

+0

Không thể sử dụng giao dịch để đồng bộ hóa mã. Nó chỉ có thể được sử dụng để * liên tục * truy cập dữ liệu. Làm thế nào các bảng bị khóa, hoặc nếu có, phụ thuộc vào mức cô lập của giao dịch. Đó là hoàn toàn khác với việc sử dụng một mutex (những thứ như SQL * Server's sp_get_applock() được đặt sang một bên). –

0

Nếu bạn không nhớ hạn chế một thread tại một thời điểm cho toàn bộ đối tượng, sau đó bạn có thể sử dụng:

Synchronization Contexts

  1. Có kế thừa lớp học của bạn từ ContextBoundObject
  2. Áp dụng một [Đồng bộ hóa] thuộc tính cho lớp học.

CLR sẽ chỉ cho phép một luồng tại một thời điểm để thực thi mã cho mỗi trường hợp của lớp này. Những người khác sẽ chặn cho đến khi khóa được giải phóng bởi luồng hiện tại.

Các vấn đề liên quan