简体   繁体   English

如何等待异步事件被调用?

[英]How do I wait for an asynchronous event to be called?

I have a method in C# that requires waiting for an event to occur. 我在C#中有一个方法,需要等待事件发生。 It's sending data to a client, but it has to wait for an event Action to be fired (which is fired when a response packet is received). 它正在将数据发送到客户端,但是它必须等待event Action被触发(在收到响应数据包时触发)。 How to I block execution of the method until the handler is called? 在调用处理程序之前,如何阻止方法的执行?

This solution worked nicely, and removes the handler from the event once it is no longer needed. 此解决方案效果很好,一旦不再需要该处理程序,便将其从事件中删除。

AutoResetEvent evt = new AutoResetEvent(false);
Action handler = () => {
  //Do stuff
  evt.Set();
}

Event += handler;
evt.WaitOne();
Event -= handler;

However, there is one major caveat (with a fairly easy workaround): The calling thread will block indefinitely until the event is called. 但是,有一个主要警告(有一个相当简单的解决方法): 调用线程将无限期阻塞,直到事件被调用为止。 This means that if the event is never called, your program will hang. 这意味着,如果永不调用该事件,则程序将挂起。 The fix for this is to simply change evt.WaitOne(); 解决方法是简单地更改evt.WaitOne(); to evt.WaitOne(SOME_TIMEOUT); evt.WaitOne(SOME_TIMEOUT);

An alternative would be to use a TaskCompletionSource See https://social.msdn.microsoft.com/Forums/en-US/a30ff364-3435-4026-9f12-9bd9776c9a01/signalling-await?forum=async 一种替代方法是使用TaskCompletionSource请参见https://social.msdn.microsoft.com/Forums/zh-CN/a30ff364-3435-4026-9f12-9bd9776c9a01/signalling-await?forum=async

It then becomes: 然后变成:

TaskCompletionSource tsc = new TaskCompletionSource<bool>();
Action handler = () => {
  //Do stuff
  tsc.SetResult(true);
}

Event += handler;
await tsc.Task;
Event -= handler;

The referenced discussion explains why this is a more lightweight solution. 所引用的讨论解释了为什么这是更轻量级的解决方案。

Also, it won't block the thread and allows for a timeout (in case the event is not called) and/or cancellation (in case the application is closed down) by using a CancellationTokenSource , see Timeout an async method implemented with TaskCompletionSource 另外,它不会阻塞线程,并且可以通过使用CancellationTokenSource允许超时(如果未调用事件)和/或取消(如果应用程序被关闭),请参见Timeout用TaskCompletionSource实现的异步方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM