如何正确创建一个等待的方法

我正在写一些等待的方法,我在互联网上找到了很多方法。 所以我来到这里是为了了解每一条路上到底发生了什么,以及是否必须放弃某些方法。

据我所知,有两种等待方法:

那些称其他等待方法的人:

public async Task GetFooAsync() { var foo = await TrulyGetFooAsync(); // Do stuff with foo return foo; } 

我没有找到任何其他方法来做到这一点,我认为这是正确的方法。 告诉我,如果我错了!

那些只称不可等待方法的人:

这里出现了问题。

例如,我看到了这个:

例1

 public async Task GetFooAsync() { return await Task.Run(() => TrulyGetFoo()); } 

据我所知,async / await关键字是无用的,可以避免这样做:

例2

 public Task GetFooAsync() { return Task.Run(() => TrulyGetFoo()); } 

最后一个例子是我到目前为止所做的事情。 关于那,是否有区别:

 Task.Run(() => TrulyGetFoo()); 

 Task.Run((Foo)TrulyGetFoo); // I don't know if the cast is required at any time but in my code, it was 

???

但我最近发现了这种方式:

例3

 public Task GetFooAsync() { TaskCompletionSource tcs = new TaskCompletionSource(); tcs.SetResult(TrulyGetFoo()); return tcs.Task; } 

如果我理解正确,一个等待的方法并不总是在另一个线程上运行??? 我的猜测是第三个例子是提供这种机制(但是如何?我只在第三个例子中看到同步代码),当示例1和2将始终在工作线程上运行时???

可能还有另外一种方法来编写等待方法,所以让我知道它们。

例如,我看到[ Task.Run包装同步代码]

这是一种不好的做法 。 我有一篇博客文章解释了为什么Task.Run应该将Task.Run用作方法实现 。

据我所知,async / await关键字是无用的,可以避免

是的,但我不建议在更复杂的方法中使用async / await

我最近发现[ TaskCompletionSource ]

如评论中所述,您的代码示例仍然是同步的。

要使其异步,您的代码应该启动一些操作并返回TaskCompletionSource.Task 。 然后,只要该操作完成,您的完成处理程序应该调用TaskCompletionSource.SetResult (或类似方法)。 有关示例,请参阅EAP的 TAP包装器或WaitHandle的TAP包装器 。

TaskFactory.FromAsync也是TaskCompletionSource 包装器,用于APM的TAP包装器 。

简短版本是这样的: async代码块中可以等待返回任务的任何内容

 public async Task MyAsyncMethod() { // do some stuff await TrulyAsyncFoo(); // do some other stuff return; } 

如果等待异步调用是该方法唯一的做法,您可以简单地返回任务本身,这将等待“上游”:

 public Task MyAsyncMethod() { return TrulyAsyncFoo(); } 

至于在异步方法中调用同步(非异步)代码,它没有任何内容。 只需像普通代码一样调用它:

 public async Task MyAsyncMethod() { MySyncMethod(); await TrulyAsyncFoo(); MyOtherSyncMethod(); } 

执行Task.Run(() => Foo())几乎总是代码气味,你没有做异步/等待权。 编写异步代码与编写multithreading代码不同。 Async只是告诉编译器您需要等待某个网络或IO绑定任务完成的好方法。

总结一下:

  • Await允许您并排编写异步和同步代码
  • 异步应仅用于等待网络或IO绑定任务,而不是计算绑定任务
  • 异步方法应始终返回TaskTask
  • 避免async void
  • 除非您知道自己在做什么,否则请避免在ASP.NET和其他线程应用程序中使用task.Wait()task.Result进行阻塞

我正在使用它来处理操作我的数据库的异步事件

 private async void btnSave_Click(object sender, EventArgs e) { success = await someClass.someMethod(some args); } 

而someMethod是这样的任务:

 public static async Task someMethod(args) { //do something here }