【问题标题】:How to use async/await with a library that uses an event-based asynchronous pattern?如何将 async/await 与使用基于事件的异步模式的库一起使用?
【发布时间】:2013-04-18 21:06:30
【问题描述】:

我使用的库有一个名为 DoWork(...) 的异步方法,该方法将在操作完成时引发 WorkDone 事件。

我想编写一个调用这个库的方法,但我不想保持相同的模式,而是希望我的方法是async,以便可以使用await 调用它。

本质上,我想做的是:

public async Task<Result> SomeMethod()
{
    var result = new Task<Result>();

    library.WorkDone += (data) =>
    {
        result.Result = data;
    }
    library.DoWork();

    return await result;
}

(不工作,因为 Result 是只读的)

这个可以吗?

【问题讨论】:

    标签: c# task-parallel-library .net-4.5 async-await c#-5.0


    【解决方案1】:

    你可以使用TaskCompletionSource:

    public async Task<Result> SomeMethod()
    {
       var result = new TaskCompletionSource<Result>();
    
       library.WorkDone += (data) =>
                                    {
                                        result.SetResult(data);
                                    };
       library.DoWork();
    
       return await result.Task;
    }
    

    【讨论】:

      【解决方案2】:

      我会以 ws0205 的回答为基础:

      首先,你表明你希望你的方法“被await”调用。您可以通过返回 Task 来实现此目的。

      我也觉得对ws0205的回答做如下调整比较好:

      public Task<Result> SomeMethod() //no async, since we're not awaiting anything
      {
         var result = new TaskCompletionSource<Result>();
      
         library.WorkDone += (data) =>
                                      {
                                          result.TrySetResult(data); //just in case 
                                      };
         library.DoWork();
      
         return result.Task; //no need to await - we're returning a Task - let the caller await (or not)
      }
      

      【讨论】:

      • 好的,也可以。我在 Web 服务器中使用它,您能否确认即使没有 async 关键字,它也不会阻塞线程?
      • @G.Stoynev 说得对,线程不会被阻塞,因为你返回了Task,使用它的人需要使用await 关键字。
      • 欲了解更多信息,see the MSDN documentation
      猜你喜欢
      • 1970-01-01
      • 2021-06-06
      • 2014-09-28
      • 2012-12-17
      • 1970-01-01
      • 2014-03-13
      • 2017-07-02
      相关资源
      最近更新 更多