C#.NET异步等待返回类型 [英] C# .NET async await return type

查看:228
本文介绍了C#.NET异步等待返回类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是希望有人可以在C#中使用asyncawait时清除返回类型.我了解您有三种返回类型,分别是Task<T>Taskvoid.

Just hoping someone could clear up return types when using async and await in C#. I understand that you have three return types being Task<T>, Task and void.

在尝试了解这一点后,我读到了您应该仅在特殊情况(事件处理程序)下使用void,如果要将同步方法更改为async方法,则应将void关键字更改为Task.

From trying to learn about this I have read you should only use void in special circumstances (Event Handlers) and if you are changing a synchronous method to an async method then you should change a void keyword to Task.

我的问题是,即使代码是完全独立的,我的结果是否也需要Task返回类型,所以对于继续而言,结果并不重要吗?例如,我使用异步方法将一些信息推送到Web服务.

My question is do I need a Task return type even though the code is completely independent and the result doesn't matter for the continuation? Say for example I use the asynchronous method to push some information to a web service.

我创建了一个小例子来帮助解释:

I have created a small example to help explain:

private void CallingMethod()
{
    AsyncMethod();
    AsyncTaskMethod(); // any difference between doing these? (not exc handling)

    var task = AsyncTaskMethod(); // should I do anything with this task
                                  // before I continue? Or is it simply 
                                  // just to show the user that it's async??

    // continue with unrelated code that doesnt require task or any code from above
}

private async void AsyncMethod() // is void okay?
{
    await LongRunningMethod();

    // do other stuff
}

private async Task AsyncTaskMethod() // or should it be Task?
{
    await LongRunningMethod();

    // do other stuff
}

private async Task LongRunningMethod()
{
    // do long running code
}

我的应用程序有很多类似这样的方法:

My application has a lot of methods like so:

private void BigMethod()
{
    DoStuff();

    DoMoreStuff();

    AsyncMethod(); // is this right? Or should I have the task declaration too?

    UnrelatedStuff();
}

private async Task AsyncMethod() // should this return task?
{
    var result = await GetUserId();

    if (result == null)
        return;

    MyUserId = result;
}

private async Task<int> GetUserId()
{
    // do long running code
    return 1;
}

如果不清楚,请务必说出来,我会尽力整理一下.谢谢大家.

If it's not clear, by all means just say and I'll try to tidy it up a bit. Thanks guys.

private void CallingMethod()
{
    AsyncMethod();
}

private async void AsyncMethod()
{
    await LongRunningMethod();
}

private async Task LongRunningMethod()
{
    await Task.Run(() =>
    {
        Thread.Sleep(4000);
    });

    MessageBox.Show("Done!");
}

作为对第一条评论的回应,上面的CallingMethod()不使用async/await,它愉快地睡眠4秒钟而不锁定UI线程,然后弹出消息框.有什么问题吗?

In response to the first comment, the above CallingMethod() does not use async/await and it happily sleeps for 4 seconds without locking up the UI thread, then pops up the message box. What's the problem?

推荐答案

当方法返回void时,您不必不必使用Task,但是对于许多情况,它确实是首选原因:

You don't have to use Task when a method returns void, but it is indeed preferred, for several reasons:

  1. 返回Task(或Task<T>)的异步方法在返回的Task上放置了异常,因此调用方法可以检查(当它们认为合适时)Task是否出错或不是.

  1. Async methods that return a Task (or Task<T>) have their exceptions put on the returned Task, so calling methods can check (when they see fit) whether the Task was faulted or not.

Async void方法将其异常直接引发在调用同步上下文中,使其几乎( nearly ,因为您仍可以使用全局异常处理程序,但这对于大型应用程序而言是不可维护的)以确定的方式处理它们上的异常.

Async void methods have their exceptions thrown directly on the calling synchronization context, making it nearly (nearly because you can still use global exception handlers, but that's unmaintainable for big applications) impossible to handle exceptions on them on a deterministic manner.

您基本上无法测试任何可能引发异常的async void方法

You basically can't test any async void methods that may throw an exception

async void方法由调用方运行时是完整的.这可能会带来很多问题(实际上,当您尝试将现有库转换为异步程序时,事件处理程序会遇到很多问题:继续,获取第三方的相对复杂的winforms库,并尝试使事件处理程序异步,您会会看到它造成的破坏!).

async void methods are assumed to be complete when they are run by the caller. This can introduce many problems (in fact, there are many problems with event handlers when you try to convert an existing library to async: go ahead, get a third-party relatively complex winforms library and try to make your event handlers async, you'll see the havoc it creates!).

没有合理的方法来确定async void方法何时完成(您可以创建自己的SynchronizationContext,但这肯定很复杂)

There is no reasonable way to determine when an async void method has finished (you could make your own SynchronizationContext, but that's something definitely complex)

您无法配置async void调用(不能在其上使用ConfigureAwait),因此继续上下文始终是调用者的同步上下文.

You can't configure an async void call (you can't use ConfigureAwait on it), so the continuation context is always the caller's synchronization context.

所以...

TL; DR:除非不能避免,否则不要使用async void(即:对于需要void签名的事件处理程序).这是有原因的.如果您不希望得到结果,请使用async Task.

TL;DR: don't use async void unless you can't avoid it (that is: with event handlers that expect a void signature). There are reasons for it. Use async Task if you don't expect a result.

这篇关于C#.NET异步等待返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆