2014-09-04 18 views
5

Tôi đang làm việc với thiết bị đọc RF có API C#. Dựa trên API của nó, bạn sẽ cần phải gọi hàm đọc của nó theo cách thủ công để đọc/đánh dấu thẻ.Ngôn ngữ C# tương đương với ScheduledExecutorService

Vì vậy, giải pháp thay thế của tôi là sử dụng Bộ hẹn giờ để thực thi đọc từng giây 'n'.

Vấn đề của tôi là Timer liên tục thực hiện, bất kể Thread.sleep() được gọi bên trong hành động của nó.

Timer timer = new Timer(TimerCallback, null, 500, 1000); // From main() method 

// The action that Timer executes 
private void TimerCallback(Object o) 
{ 
    scan(); // Action for reading/badging card 
    scand.WaitOne(); // AutoResetEvent(true) 
    GC.Collect(); // Force garbage collection 
} 

Thread.sleep() gọi bên trong quá trình quét().

Trong Java, tôi sử dụng đồng bộ() để đợi chuỗi khác gọi invoke(). Tôi đã tìm kiếm cả ngày và tôi không thể thấy một giải pháp thay thế sẽ tương đương với ScheduledExecutorService và được đồng bộ hóa().

Tôi hy vọng có một giải pháp với nguyên nhân này tôi cần nó càng sớm càng tốt.

Cảm ơn!

+0

bạn đã có một cái nhìn tại các lớp công tác ? http://stackoverflow.com/questions/13211334/how-do-i-wait-until-task-is-finished-in-c – fuchs777

+0

Tôi thấy lớp Task khi tôi đang tìm kiếm nhưng mã @Erno de Weerd đã được giải quyết vấn đề của tôi. Nhưng dù sao cũng được. –

Trả lời

2

Cách đáng tin cậy nhất tôi có thể tìm thấy là bằng cách khởi động lại bộ hẹn giờ trong cuộc gọi lại. Bằng cách này, gọi lại không bị gián đoạn khi hoạt động.

Timer timer = new Timer(TimerCallback, null, 500, 0); 

private void TimerCallback(Object o) 
{ 
    scan(); 
    scand.WaitOne(); 
    timer.Change(500, 0); 
} 

timer.Change sắp xếp lại hẹn giờ.

Lưu ý: Tôi đã xóa sự lặp lại trong khởi động Bộ hẹn giờ.

BTW: Tôi đã xóa GC.Collect() vì tôi cho rằng thực tiễn không tốt và vô dụng trong hầu hết các trường hợp.

Ngoài ra bạn có thể nhận được thời gian lúc bắt đầu của phương pháp này (Sử dụng Stopwatch) và tính toán đồng bằng thời gian cần thiết để được thông qua để timer.Change:

Timer timer = new Timer(TimerCallback, null, 500, 0); 
Stopwatch stopwatch = Stopwatch.StartNew(); 

private void TimerCallback(Object o) 
{ 
    var entered = stopwatch.ElapsedMilliseconds; 
    scan(); 
    scand.WaitOne(); 
    var duration = stopwatch.ElapsedMilliseconds - entered; 
    var delay = Math.Max(0, 500 - duration); 
    timer.Change(delay, 0); 
} 

Bằng cách này, callback sẽ được gọi sau khi 500 ms trừ đi thời gian để thực hiện các chức năng quét. Thiết lập như thế này và bạn có thể xóa chế độ Ngủ khỏi Quét.

Lý do cho cuộc gọi lại kép trong mã của bạn có thể là bộ đếm thời gian thực thi cuộc gọi lại trên một chuỗi khác khi chuỗi đầu tiên vẫn đang thực hiện cuộc gọi lại.

Một giải pháp khác có thể là không sử dụng Timer. Chỉ cần lặp và sử dụng một Stopwatch để tính toán một khoảng thời gian để ngủ:

private void Scan() 
{ 
    while(scanning) 
    { 
     var entered = stopwatch.ElapsedMilliseconds; 
     scan(); 
     scand.WaitOne(); 
     var duration = stopwatch.ElapsedMilliseconds - entered; 
     var delay = Math.Max(0, 500 - duration); 
     Thread.Sleep(delay); 
    } 
} 

Đảm bảo bạn gọi phương pháp này trên một sợi riêng biệt (bạn có thể sử dụng một Task)

+0

Cảm ơn bạn đã trả lời ngắn gọn. Chính xác, vấn đề của tôi là mã hiện tại của tôi là kết quả của một callback bị trì hoãn vô tận. Mã minh họa thứ 2 của bạn là mã tôi sử dụng và nó hoạt động hoàn hảo như tôi yêu cầu. Đề nghị 'timer.Change()' của bạn đã làm các trick. Cảm ơn! –

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