.jpg)
根据我的理解,主要的事情之一是使代码易于编写和阅读 – 但是使用它们是否等于生成后台线程来执行长时间的逻辑?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;
}
好的,那么这里会发生什么:
Task<int> longRunningTask = LongRunningOperationAsync();开始执行LongRunningOperationawait 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#】栏目查找您需要的精美模板。