首页 > C# > 如何以及何时使用“异步”和“等待”

如何以及何时使用“异步”和“等待”

上一篇 下一篇

根据我的理解,主要的事情之一是使代码易于编写和阅读 – 但是使用它们是否等于生成后台线程来执行长时间的逻辑?asyncawait

我目前正在尝试最基本的示例。我添加了一些内联评论。你能为我澄清一下吗?

// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
    Task<int> access = DoSomethingAsync();
    // task independent stuff here

    // this line is reached after the 5 seconds sleep from 
    // DoSomethingAsync() method. Shouldn't it be reached immediately? 
    int a = 1; 

    // from my understanding the waiting should be done here.
    int x = await access; 
}

async Task<int> DoSomethingAsync()
{
    // is this executed on a background thread?
    System.Threading.Thread.Sleep(5000);
    return 1;
}

分割线

网友回答:

根据我的理解,async 和 await 所做的主要事情之一是使代码易于编写和阅读。

它们是为了使异步代码易于编写和读取,是的。

它与生成后台线程以执行长时间逻辑是一回事吗?

一点也不。

我不明白为什么必须将此方法标记为“异步”。

关键字启用关键字。因此,使用的任何方法都必须标记。asyncawaitawaitasync

在 DoSomethingAsync() 方法的 5 秒睡眠后到达此行。不应该立即到达吗?

否,因为默认情况下,方法不会在另一个线程上运行。async

这是在后台线程上执行的吗?

不。


您可能会发现我的/介绍很有帮助。官方的MSDN文档也异常出色(尤其是TAP部分),团队发布了一个出色的FAQ。asyncawaitasync
分割线

网友回答:

使用 时,编译器在后台生成状态机。asyncawait

下面是一个示例,我希望我可以解释一些正在进行的高级细节:

public async Task MyMethodAsync()
{
    Task<int> longRunningTask = LongRunningOperationAsync();
    // independent work which doesn't need the result of LongRunningOperationAsync can be done here

    //and now we call await on the task 
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result);
}

public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation 
{
    await Task.Delay(1000); // 1 second delay
    return 1;
}

好的,那么这里会发生什么:

  1. Task<int> longRunningTask = LongRunningOperationAsync();开始执行LongRunningOperation
  2. 独立工作完成,假设主线程(线程 ID = 1)然后到达。await longRunningTask现在,如果 尚未完成并且仍在运行,将返回到其调用方法,因此主线程不会被阻塞。完成后,来自 ThreadPool 的线程(可以是任何线程)将返回到其先前上下文中并继续执行(在本例中将结果打印到控制台)。longRunningTaskMyMethodAsync()longRunningTaskMyMethodAsync()

第二种情况是 已经完成了执行并且结果可用。当到达时,我们已经有了结果,因此代码将继续在同一线程上执行。(在本例中,将结果打印到控制台)。当然,上述示例并非如此,其中涉及一个。longRunningTaskawait longRunningTaskTask.Delay(1000)
分割线

网友回答:

解释

下面是 / 的快速示例。除此之外,还有更多细节需要考虑。asyncawait

注意:模拟做工作 1 秒。我认为最好将其视为等待来自外部资源的响应。由于我们的代码正在等待响应,因此系统可以将正在运行的任务放在一边,并在完成后返回该任务。同时,它可以在该线程上执行其他一些工作。Task.Delay(1000)

在下面的示例中,第一个块正是这样做的。它立即启动所有任务(行)并将它们放在一边。代码将在行上暂停,直到完成 1 秒延迟,然后转到下一行。由于 、、 和 几乎在完全相同的时间开始执行(由于缺少等待),在这种情况下,它们应该在大致相同的时间完成。Task.Delayawait abcdea

在下面的示例中,第二个块是启动任务并等待它完成(这就是完成的任务),然后再启动后续任务。每次迭代需要 1 秒。正在暂停程序并等待结果,然后再继续。这是第一个和第二个块之间的主要区别。awaitawait

Console.WriteLine(DateTime.Now);

// This block takes 1 second to run because all
// 5 tasks are running simultaneously
{
    var a = Task.Delay(1000);
    var b = Task.Delay(1000);
    var c = Task.Delay(1000);
    var d = Task.Delay(1000);
    var e = Task.Delay(1000);

    await a;
    await b;
    await c;
    await d;
    await e;
}

Console.WriteLine(DateTime.Now);

// This block takes 5 seconds to run because each "await"
// pauses the code until the task finishes
{
    await Task.Delay(1000);
    await Task.Delay(1000);
    await Task.Delay(1000);
    await Task.Delay(1000);
    await Task.Delay(1000);
}
Console.WriteLine(DateTime.Now);

输出:

5/24/2017 2:22:50 PM
5/24/2017 2:22:51 PM (First block took 1 second)
5/24/2017 2:22:56 PM (Second block took 5 seconds)

有关同步上下文的额外信息

注意:这就是事情对我来说有点模糊的地方,所以如果我在任何事情上错了,请纠正我,我会更新答案。对它的工作原理有一个基本的了解很重要,但只要你从不使用,你就可以不成为它的专家,尽管你可能会失去一些优化的机会,我认为。ConfigureAwait(false)

这有一个方面使/概念有点难以掌握。事实上,在这个例子中,这一切都发生在同一个线程上(或者至少在它的 .默认情况下, 将还原运行它的原始线程的同步上下文。例如,在 ASP.NET 中,当请求进入时,您有一个与线程相关联的线程。此上下文包含特定于原始 Http 请求的内容,例如原始请求对象,其中包含语言、IP 地址、标头等内容。如果您在处理某些内容的过程中切换线程,则最终可能会尝试从另一个对象中提取信息,这可能是灾难性的。如果你知道你不会将上下文用于任何事情,你可以选择“不关心”它。这基本上允许你的代码在单独的线程上运行,而无需随之带来上下文。asyncawaitSynchronizationContextawaitHttpContextHttpContext

您如何实现这一目标?默认情况下,代码实际上是在假设您确实想要捕获和还原上下文:await a;

await a; //Same as the line below
await a.ConfigureAwait(true);

如果要允许主代码在没有原始上下文的情况下继续在新线程上,只需使用 false 而不是 true,这样它就知道它不需要恢复上下文。

await a.ConfigureAwait(false);

程序暂停完成后,它可能会在具有不同上下文的完全不同的线程上继续。这就是性能改进的来源——它可以在任何可用的线程上继续,而不必恢复它开始的原始上下文。

这东西令人困惑吗?地狱是的!你能弄清楚吗?可能!一旦你掌握了这些概念,然后继续斯蒂芬·克利里的解释,这些解释往往更适合那些对/已经有技术理解的人。asyncawait

模板简介:该模板名称为【如何以及何时使用“异步”和“等待”】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【C#】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 283次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 02-16
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
微信公众平台 微信模板 企业网站 微信文章 响应式 html5 自适应 单页式简历模板 微信素材 微信图片
您可能会喜欢的其他模板