[英]Is there a way to prevent an event handler from firing over itself?
我有一個可以快速連續發生的事件的事件處理程序。 在某些情況下,當事件再次觸發時(毫秒內),處理程序仍將執行。
有沒有辦法讓這些處理程序......串行? 那么,在事件調用 #1 完成之前,事件調用 #2 無法啟動?
如果這是一個糟糕的想法,為什么? 這是一個在后台無人值守運行的批處理過程,因此我並不十分擔心一個調用阻塞另一個調用可能會出現性能問題。
使用多線程控制lock
。 這樣可以防止您的代碼在同一時刻多次運行。
EDITED
例:
public class Foo
{
private static object _lockKey = new object();
private void YourEventHandlerMethod(object sender, EventArgs e)
{
lock (_lockKey)
{
// the code you put inside this block will be execute only
// once at time.
// If a second call has the intention to use this block before
// the conclusion of the first call, the second call (the thread)
// will be put in hold.
}
}
}
有一些選項可以序列化事件的處理,這些事件可以從多個線程並發或通過重新加密/遞歸在同一線程上觸發。
選項之一是使用任務計划程序。 在您的方案中,任務計划程序的目的是使回調排隊,以便以后進行串行執行。 諸如此類的任務計划程序的一個著名概念示例是WinForms消息循環(以Application.Run
開始,以Control.BeginInvoke
排隊)和WPF Dispatcher循環(以Dispatcher.Run
開始,以Dispatcher.BeginInvoke
或Dispatcher.InvokeAsync
排隊)。
TPL任務計划程序的一個StaTaskScheduler
但非常有用的實現是Stephen Toub的StaTaskScheduler
。 我在這里和這里都發布了一些基於它的代碼(后一個是來自一個非常接近的問題, 異步執行的隊列操作/委托 )。
此處介紹了另一個選擇: 任務排序和重新登錄 。
在這種情況下,將處理程序作為任務組成,每個新的處理程序都在前一個任務完成后啟動。
八年后,我發現了阻塞收藏的樂趣。
與其讓事件處理程序完成這項工作,我還可以將一些數據放入一個阻塞集合中,並有一個單獨的線程來處理它。
private readonly BlockingCollection<Whatever> queue = new BlockingCollection<Whatever>();
Task.Run(() =>
{
while (!queue.IsCompleted) {
// Do whatever
}
}
// Then just add a bunch of stuff to it
queue.Add(new Whatever());
// It will just keep working the queue in a separate thread, going back for a new Whatever whenever it's done
// You can even start multiple threads to work the queue. They won't interfere with each other
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.