Vin*_*ent 40 c# asynchronous async-await
我一直在研究如何使用异步等待,但是当我们有多个互相调用的方法时,我不太了解它。我们应该始终使用等待还是仅在实际准备好使用结果时才使用等待?
因此,例如,我们应该这样做吗:
async Task<string[]> FooAsync()
{
var info = await Func1();
return info.split('.');
}
async Task<string> Func1()
{
return await Func2();
}
async Task<string> Func2()
{
return await tcpClient.ReadStringAsync();
}
Run Code Online (Sandbox Code Playgroud)
或像这样:
async Task<string[]> FooAsync()
{
var info = await Func1();
return info.split('.');
}
Task<string> Func1()
{
return Func2();
}
Task<string> Func2()
{
return tcpClient.ReadStringAsync();
}
Run Code Online (Sandbox Code Playgroud)
根据示例1,我们应该在每种方法中始终使用await吗?
还是
按照示例2,当我们开始使用结果时,我们应该只在最上面的方法上使用await吗?
AAA*_*ddd 28
每次您调用await它时,都会创建大量代码来捆绑变量,捕获同步上下文(如果适用)并在中创建延续IAsyncStateMachine。
从本质上讲,返回Task不带async 关键字的 a将给您带来很小的运行时效率,并节省了许多CIL。请注意,.NET中的Async功能也已经进行了许多优化。还要注意(并且重要的是)在语句中返回a 可能会引发Already Disposed Exception。Taskusing
您可以在此处比较CIL和管道的差异
因此,如果您的方法只是转发a Task而不想要任何东西,则可以轻松地删除async关键字并Task直接返回。
而且,有时候我们要做的不只是转发,还涉及分支。这是在哪里,Task.FromResult并Task.CompletedTask开始发挥作用,协助处理的方法可能会出现什么逻辑。即,如果您要给出一个结果(然后然后),或分别返回一个Task已完成的结果。
最后,异步和等待模式在处理Exception时有细微的差别。如果您要传回Task,则可以像通常方法一样使用Task.FromException<T>,在传回的讯息上弹出任何例外。Taskasync
荒谬的例子
public Task<int> DoSomethingAsync(int someValue)
{
try
{
if (someValue == 1)
return Task.FromResult(3); // Return a completed task
return MyAsyncMethod(); // Return a task
}
catch (Exception e)
{
return Task.FromException<int>(e); // Place exception on the task
}
}
Run Code Online (Sandbox Code Playgroud)
简而言之,如果您不太了解正在发生的事情,await那就去吧。开销将最小。但是,如果您了解如何返回任务结果,完成的任务,在任务上放置异常或只是转发的字幕。通过删除直接返回任务并绕过关键字的关键字,可以节省一些CIL,并使代码的性能有所提高。asyncIAsyncStateMachine
大约在这个时候,我将查找Stack Overflow用户和作者Stephen Cleary以及Parallel Stephen Toub先生。他们有大量的博客和书籍,专门讨论异步和等待模式,所有陷阱,编码礼节以及许多您肯定会感兴趣的信息。
Fab*_*bio 12
这两个选项都是合法的,每个选项都有自己的场景,在这种情况下,它比另一个更有效。
当然,当您要处理异步方法的结果或处理当前方法中可能的异常时,请始终使用await
public async Task Execute()
{
try
{
await RunAsync();
}
catch (Exception ex)
{
// Handle thrown exception
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不在当前方法中使用异步方法的结果,请返回Task。这种方法将延迟状态机的创建到调用者或将要等待最终任务的地方。正如评论中指出的那样,可以使执行更有效率。
但是在某些情况下,您必须等待任务,即使您对结果什么也不做,也不想处理可能的异常
public Task<Entity> GetEntity(int id)
{
using (var context = _contextFactory.Create())
{
return context.Entities.FindAsync(id);
}
}
Run Code Online (Sandbox Code Playgroud)
在上述情况下,FindAsync可以返回未完成的任务,并且此任务将立即返回给调用方并处理context在using语句中创建的对象。
稍后当调用者将“等待”任务时,将抛出异常,因为它将尝试使用已处置的object(context)。
public async Task<Entity> GetEntity(int id)
{
using (var context = _contextFactory.Create())
{
return await context.Entities.FindAsync(id);
}
}
Run Code Online (Sandbox Code Playgroud)
传统上,有关Async Await的答案必须包含指向Stephen Cleary的博客Eliding Async and Await的链接
| 归档时间: |
|
| 查看次数: |
3085 次 |
| 最近记录: |