【问题标题】:How do I wait for an asynchronous event to be called?如何等待调用异步事件?
【发布时间】:2016-06-09 19:20:56
【问题描述】:

我在 C# 中有一个需要等待事件发生的方法。它正在向客户端发送数据,但它必须等待event Action 被触发(在收到响应数据包时触发)。如何在调用处理程序之前阻止方法的执行?

【问题讨论】:

    标签: c#


    【解决方案1】:

    这个解决方案效果很好,一旦不再需要处理程序,它就会从事件中删除。

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

    但是,有一个主要的警告(有一个相当简单的解决方法):调用线程将无限期地阻塞,直到事件被调用。这意味着如果从不调用事件,您的程序将悬挂。解决此问题的方法是将evt.WaitOne(); 更改为evt.WaitOne(SOME_TIMEOUT);

    【讨论】:

    • 如果您只是在等待一个,为什么不使用 ManualResetEventSlim?您实际上并不需要重置它,如果您期望快速响应,Slim 会提供稍微更好的性能。
    • 好问题。可能应该。
    【解决方案2】:

    另一种方法是使用TaskCompletionSource 请参阅https://social.msdn.microsoft.com/Forums/en-US/a30ff364-3435-4026-9f12-9bd9776c9a01/signalling-await?forum=async

    然后变成:

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

    引用的讨论解释了为什么这是一个更轻量级的解决方案。

    此外,它不会阻塞线程并允许使用CancellationTokenSource 进行超时(以防事件未调用)和/或取消(以防应用程序关闭),请参阅Timeout an async method implemented with TaskCompletionSource

    【讨论】:

    • 碰巧,我的解决方案以此为基础——我只是认为使用等待句柄会更快。
    猜你喜欢
    • 2022-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多