C# .NET 3.5:如何调用事件处理程序并等待它完成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/582627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# .NET 3.5 : How to invoke an event handler and wait for it to complete
提问by rc1
I have a class containing a worker thread which receives data from a queue in a loop.
我有一个包含工作线程的类,它从循环中的队列接收数据。
Another part of the app sinks an event from this class, which the class raises for each queue item.
应用程序的另一部分从此类接收一个事件,该类为每个队列项引发该事件。
These events are fired asynchronously, so at busy times the other part of the app can be processing several events at once.
这些事件是异步触发的,因此在繁忙时间,应用程序的其他部分可以同时处理多个事件。
This should be fine but we've discovered a scenario where this can cause problems.
这应该没问题,但我们发现了一个可能会导致问题的场景。
We need a quick solution while the main issue gets addressed. Does the framework provide a simple way I can force the worker thread to wait while each event gets processed (so they are processed sequentially)? If not, what's the easiest way to implement this?
在解决主要问题的同时,我们需要一个快速的解决方案。框架是否提供了一种简单的方法,我可以强制工作线程在处理每个事件时等待(因此它们按顺序处理)?如果没有,实现这一点的最简单方法是什么?
采纳答案by eduesing
A simple answer would be to lock() on a single object in the event handler. All of the theads would wait to get the lock.
一个简单的答案是在事件处理程序中的单个对象上使用 lock()。所有的 theads 都会等待获得锁。
回答by Richard
There is no general way.
没有通用的方法。
In the end the handlers need to provide a mechanism for tracking.
最后,处理程序需要提供一种跟踪机制。
If you are using BeginInvoke, rather than raising the events directly, you can use a wrapper, within which you call the real event handler synchronously, then raise the wrapper asynchronously. The wrapper can maintain a counter (with Interlocked operations) or set an event as meets your needs.
如果您使用的是 BeginInvoke,而不是直接引发事件,则可以使用包装器,在其中同步调用实际事件处理程序,然后异步引发包装器。包装器可以维护一个计数器(使用互锁操作)或根据您的需要设置一个事件。
Something like:
就像是:
TheDelegate realHandler = theEvent;
var outer = this;
ThreadPool.QuereUserWorkItem(x => {
// Set start of handler
realHandler(outer, eventArgs);
// Set handler finished
};
回答by Yes - that Jake.
All of the event handlers sinking events raised by the queue-reading worker thread are called in the queue-reading worker thread. As long as the event handlers aren't spawning threads of their own, you should be able to wait for the event handlers to finish by calling Thread.Join() on the queue-reading worker thread.
所有接收队列读取工作线程引发的事件的事件处理程序都在队列读取工作线程中调用。只要事件处理程序没有产生自己的线程,您就应该能够通过在队列读取工作线程上调用 Thread.Join() 来等待事件处理程序完成。
回答by Mitchel Sellers
My guess is that you want to simply go away from triggering the action by raising an event and calling the method directly.
我的猜测是,您只想通过引发事件并直接调用方法来避免触发操作。
AFAIK events are going to be async and I am not aware of any "easy" ways of changing that.
AFAIK 事件将是异步的,我不知道有任何“简单”的方法可以改变它。
回答by lc.
The ManualResetEvent classmight help you here, unless I'm not understanding your question. You can use it to block the firing of the next event until the last one completes.
该ManualResetEvent的类可以帮助你在这里,除非我不理解你的问题。您可以使用它来阻止下一个事件的触发,直到最后一个事件完成。
回答by eduesing
Turns out there's another answer. You can just add the following attribute to the method.
原来还有另一个答案。您可以将以下属性添加到方法中。
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]