async 和 await小结

你可以先回顾一下之前的异步操作方式(来自我们stackoverflow的总结):中文翻译:https://codeday.me/bug/20170709/39452.html

https://stackoverflow.com/questions/1047662/what-is-asynccallback

总的来说,第一种方式,使用我们的回调的方式;在我们的callback中处理 异步之后完成的之间; 没去堵塞我们额主线程;

如果callback之后还有异步请求,那么久出现了我们的callback hell的 层层嵌套的模式;

解决这种方式就是使用我们的 promise 方式的continue 的模式;

和之前的集中方式的比较:

https://msdn.microsoft.com/zh-cn/library/jj152938

能够很好的说明aync 和 awati 流程的一张图;

关于代码中是否配置我们的configure 的使用的解释:

1)当ConfigureAwait(true),代码由同步执行进入异步执行时,当前同步执行的线程上下文信息(比如HttpConext.Current,Thread.CurrentThread.CurrentCulture)就会被捕获并保存至SynchronizationContext中,供异步执行中使用,并且供异步执行完成之后(await之后的代码)的同步执行中使用(虽然await之后是同步执行的,但是发生了线程切换,会在另外一个线程中执行「ASP.NET场景」)。这个捕获当然是有代价的,当时我们误以为性能问题是这个地方的开销引起,但实际上这个开销很小,在我们的应用场景不至于会带来性能问题。

2)当Configurewait(flase),则不进行线程上下文信息的捕获,async方法中与await之后的代码执行时就无法获取await之前的线程的上下文信息,在ASP.NET中最直接的影响就是HttpConext.Current的值为null。

我们在犯傻过程中,工作量最大的就是处理HttpConext.Current为null的情况。

由于之前写代码时的幼稚与偷懒,造成了很多地方用HttpConext.Current去获取http请求相关信息。在异步化改造之后,HttpConext.Current也遍布在很多aync方法中。Configurewait(flase)之后,NullReferenceException如雨后春笋。

原文来自这里:

http://www.cnblogs.com/cmt/p/configure_await_false.html

三大返回值;

  • 返回类型 - Task<TResult> 
  • 返回类型 - Task
  • 返回类型 - void

当你添加 async 关键字后,需要返回一个将用于后续操作的对象,请使用 Task<TResult>。

当你如果只是想知道执行的状态,而不需要知道具体的返回结果时,请使用 Task。

当你如果在触发后,你不想管了,请使用 void。如事件处理程序。

ps:这里还有一篇好文章;https://msdn.microsoft.com/zh-cn/magazine/jj991977.aspx

一些异步编程的实践原理;

1.避免 Async Void

当 async Task 或 async Task<T> 方法引发异常时,会捕获该异常并将其置于 Task 对象上。 

对于 async void 方法,没有 Task 对象,因此 async void 方法引发的任何异常都会直接在 SynchronizationContext(在 async void 方法启动时处于活动状态)上引发

private async void ThrowExceptionAsync()
{
  throw new InvalidOperationException();
}
public void AsyncVoidExceptions_CannotBeCaughtByCatch()
{
  try
  {
    ThrowExceptionAsync();
  }
  catch (Exception)
  {
    // The exception is never caught here!
throw;
  }
}

 Async void 方法具有不同的组合语义。 返回 Task 或 Task<T> 的 async 方法可以使用 await、Task.WhenAny、Task.WhenAll 等方便地组合而成。

 返回 void 的 async 方法未提供一种简单方式,用于向调用代码通知它们已完成。 启动几个 async void 方法不难,但是确定它们何时结束却不易。 

 Async void 方法会在启动和结束时通知 SynchronizationContext,但是对于常规应用程序代码而言,自定义 SynchronizationContext 是一种复杂的解决方案。

did you konw what is different below the code?

        static Task<string> GetStringInfoQ()
        {
            using (var wc = new System.Net.WebClient())
            {
                return  wc.DownloadStringTaskAsync("http://www.linqpad.net"); 
            }
        }

        static async Task<string> getDownloadString()
        {
            using (var wc = new System.Net.WebClient())
            {
                return  await wc.DownloadStringTaskAsync("http://www.linqpad.net"); 
            }
        }
原文地址:https://www.cnblogs.com/mc67/p/6259297.html