C# 如何等待异步方法完成?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15149811/
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
How to wait for async method to complete?
提问by bmt22033
I'm writing a WinForms application that transfers data to a USB HID class device. My application uses the excellent Generic HID library v6.0 which can be found here. In a nutshell, when I need to write data to the device, this is the code that gets called:
我正在编写一个将数据传输到 USB HID 类设备的 WinForms 应用程序。我的应用程序使用了优秀的通用 HID 库 v6.0,可以在这里找到。简而言之,当我需要将数据写入设备时,这是调用的代码:
private async void RequestToSendOutputReport(List<byte[]> byteArrays)
{
foreach (byte[] b in byteArrays)
{
while (condition)
{
// we'll typically execute this code many times until the condition is no longer met
Task t = SendOutputReportViaInterruptTransfer();
await t;
}
// read some data from device; we need to wait for this to return
RequestToGetInputReport();
}
}
When my code drops out of the while loop, I need to read some data from the device. However, the device isn't able to respond right away so I need to wait for this call to return before I continue. As it currently exists, RequestToGetInputReport() is declared like this:
当我的代码退出 while 循环时,我需要从设备读取一些数据。但是,设备无法立即响应,因此我需要等待此调用返回,然后才能继续。由于它目前存在,RequestToGetInputReport() 声明如下:
private async void RequestToGetInputReport()
{
// lots of code prior to this
int bytesRead = await GetInputReportViaInterruptTransfer();
}
For what it's worth, the declaration for GetInputReportViaInterruptTransfer() looks like this:
值得一提的是,GetInputReportViaInterruptTransfer() 的声明如下所示:
internal async Task<int> GetInputReportViaInterruptTransfer()
Unfortunately, I'm not very familiar with the workings of the new async/await technologies in .NET 4.5. I did a little reading earlier about the await keyword and that gave me the impression that the call to GetInputReportViaInterruptTransfer() inside of RequestToGetInputReport() would wait (and maybe it does?) but it doesn't seem like the call to RequestToGetInputReport() itself is waiting because I seem to be re-entering the while loop almost immediately?
不幸的是,我不太熟悉 .NET 4.5 中新的 async/await 技术的工作原理。我之前阅读了一些关于 await 关键字的内容,这给我的印象是在 RequestToGetInputReport() 内部调用 GetInputReportViaInterruptTransfer() 会等待(也许它会等待?)但它似乎不像对 RequestToGetInputReport() 的调用本身正在等待,因为我似乎几乎立即重新进入 while 循环?
Can anyone clarify the behavior that I'm seeing?
任何人都可以澄清我所看到的行为吗?
采纳答案by Stephen Cleary
Avoid async void
. Have your methods return Task
instead of void
. Then you can await
them.
避免async void
。让您的方法返回Task
而不是void
. 然后你就可以await
了。
Like this:
像这样:
private async Task RequestToSendOutputReport(List<byte[]> byteArrays)
{
foreach (byte[] b in byteArrays)
{
while (condition)
{
// we'll typically execute this code many times until the condition is no longer met
Task t = SendOutputReportViaInterruptTransfer();
await t;
}
// read some data from device; we need to wait for this to return
await RequestToGetInputReport();
}
}
private async Task RequestToGetInputReport()
{
// lots of code prior to this
int bytesRead = await GetInputReportViaInterruptTransfer();
}
回答by Richard Cook
The most important thing to know about async
and await
is that await
doesn'twait for the associated call to complete. What await
does is to return the result of the operation immediately and synchronously if the operation has already completedor, if it hasn't, to schedule a continuation to execute the remainder of the async
method and then to return control to the caller. When the asynchronous operation completes, the scheduled completion will then execute.
最重要的是要了解async
并await
是await
不等待完成相关的呼叫。什么await
做的是立即地,同步返回操作的结果如果操作已经完成,或者,如果没有,安排的延续,执行的剩余async
方法,然后将控制返回给调用者。异步操作完成后,将执行计划完成。
The answer to the specific question in your question's title is to block on an async
method's return value (which should be of type Task
or Task<T>
) by calling an appropriate Wait
method:
问题标题中特定问题的答案是通过调用适当的方法来阻止async
方法的返回值(应为Task
或类型Task<T>
)Wait
:
public static async Task<Foo> GetFooAsync()
{
// Start asynchronous operation(s) and return associated task.
...
}
public static Foo CallGetFooAsyncAndWaitOnResult()
{
var task = GetFooAsync();
task.Wait(); // Blocks current thread until GetFooAsync task completes
// For pedagogical use only: in general, don't do this!
var result = task.Result;
return result;
}
In this code snippet, CallGetFooAsyncAndWaitOnResult
is a synchronouswrapper around asynchronous method GetFooAsync
. However, this pattern is to be avoided for the most part since it will block a whole thread pool thread for the duration of the asynchronous operation. This an inefficient use of the various asynchronous mechanisms exposed by APIs that go to great efforts to provide them.
在此代码片段中,CallGetFooAsyncAndWaitOnResult
是异步方法的同步包装器GetFooAsync
。但是,在大多数情况下应避免这种模式,因为它会在异步操作期间阻塞整个线程池线程。这是对 API 公开的各种异步机制的低效使用,而这些异步机制付出了巨大的努力来提供它们。
The answer at "await" doesn't wait for the completion of callhas several, more detailed, explanations of these keywords.
“await”处的答案不等待调用完成,对这些关键字有几个更详细的解释。
Meanwhile, @Stephen Cleary's guidance about async void
holds. Other nice explanations for why can be found at http://www.tonicodes.net/blog/why-you-should-almost-never-write-void-asynchronous-methods/and https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.html
同时,@Stephen Cleary 关于async void
保留的指导。关于原因的其他很好的解释可以在http://www.tonicodes.net/blog/why-you-should-almost-never-write-void-asynchronous-methods/和https://jaylee.org/archive/找到2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.html
回答by Jerther
The following snippet shows a way to ensure the awaited method completes before returning to the caller. HOWEVER, I wouldn't say it's good practice. Please edit my answer with explanations if you think otherwise.
以下代码段显示了一种确保等待的方法在返回调用者之前完成的方法。但是,我不会说这是一种很好的做法。如果您不这么认为,请编辑我的答案并解释。
public async Task AnAsyncMethodThatCompletes()
{
await SomeAsyncMethod();
DoSomeMoreStuff();
await Task.Factory.StartNew(() => { }); // <-- This line here, at the end
}
await AnAsyncMethodThatCompletes();
Console.WriteLine("AnAsyncMethodThatCompletes() completed.")
回答by Ram chittala
Best Solution to wait AsynMethod till complete the task is
等待 AsynMethod 直到完成任务的最佳解决方案是
var result = Task.Run(async() => await yourAsyncMethod()).Result;
回答by Bar?? Tanyeri
Actually I found this more helpful for functions that return IAsyncAction.
实际上我发现这对返回 IAsyncAction 的函数更有帮助。
var task = asyncFunction();
while (task.Status == AsyncStatus.Completed) ;
回答by Firas Nizam
just put Wait() to wait until task completed
只需放置 Wait() 等待任务完成
GetInputReportViaInterruptTransfer().Wait();
GetInputReportViaInterruptTransfer().Wait();
回答by shocky lemi
Here is a workaround using a flag:
这是使用标志的解决方法:
//outside your event or method, but inside your class
private bool IsExecuted = false;
private async Task MethodA()
{
//Do Stuff Here
IsExecuted = true;
}
.
.
.
//Inside your event or method
{
await MethodA();
while (!isExecuted) Thread.Sleep(200); // <-------
await MethodB();
}