我读了很多文章,仍然无法理解这一部分。
考虑这个代码:
private async void button1_Click(object sender, EventArgs e)
{
await Dosomething();
}
private async Task<string> Dosomething()
{
await Task.Run((() => "Do Work"));
return "I am done";
}
第一个问题:
当我单击该按钮时,它将调用DoSomething并等待一个Task,该Task通过调用Task.Run(如果我没有错的话(从线程池创建线程,所有这些都异步运行。所以我实现了创建一个线程来完成我的工作,但异步完成?但考虑到我不需要返回任何结果,我只想在不返回任何结果的情况下完成工作,真的需要使用async/await吗?如果需要,如何使用?
第二个问题:
异步运行线程时,这是如何工作的?它是在主UI上运行,但在一个单独的线程上运行,还是在一个独立的线程上,并在该方法中异步运行?
- 创建异步方法的目的是为了以后可以等待它们。有点像"我要把水烧开,把剩下的汤料准备好,然后回到锅里,等水烧开了,这样我就可以做晚饭了。",但最终你必须停下来等待它。如果你想要的是"即发即弃",那么Async和Await就没有必要了
在C#中执行fire-and-forget方法的最简单方法?
- 启动新任务会将该任务排入队列,以便在线程池线程上执行。线程在进程的上下文中执行(例如,运行应用程序的可执行文件(。如果这是在IIS下运行的web应用程序,则该线程是在IIS工作进程的上下文中创建的。该线程与主执行线程是分开执行的,因此无论主执行线程在做什么,它都会停止并执行自己的任务,同时,主执行线程继续执行自己的工作
1
如果你不await
Task
或await
它有很大的区别:
-
如果您没有
await
,则:调用DoSomething
,但执行下一句,而DoSomething
Task
尚未完成。 -
如果您
await
它:调用DoSomething
,一旦DoSomething
Task
完成,就执行下一句话。
因此,async
/await
的需求将取决于您想要如何调用DoSomething
:如果您不调用await
,则将其称为fire&忘记方式。
2
它是在主UI上运行,但在单独的线程上运行,还是在运行在一个单独的线程上,而separate在其中异步方法
异步代码有时意味着其他线程(请参阅本问答异步与多线程-有区别吗?(。也就是说,如果代码是在独立于UI的线程中执行的,或者它允许在恢复UI线程时继续处理UI线程,这很好,因为UI循环仍然可以在并行执行其他任务时更新屏幕,而不会冻结UI。
异步方法(即async
方法(是一种语法糖,用来告诉编译器await
语句应该被视为状态机。C#编译器将async
/await
代码转换为一个状态机,在该状态机中,等待Task
结果的代码将在等待的代码之后执行。
有趣的问答;作为
你可能想复习一下其他的问答;As:
- 异步/等待与线程
- 什么';Task.Start/Wait和Async/Await有什么区别
- async/await-什么时候返回Task vs void
- Async await关键字是否等效于ContinueWith lambda
OP说
[…]但这是否意味着"async/await"将启动一个线程并Task。Run也会触发一个线程,还是它们都是同一个线程?
使用async
-await
并不意味着"我创建了一个线程">。以一种优雅的方式实现延续只是一种语法糖。任务可能是线程,也可能不是线程。例如,Task.FromResult(true)
创建了一个伪任务,以便能够实现异步方法,而无需创建线程:
public Task<bool> SomeAsync()
{
// This way, this method either decides if its code is asynchronous or
// synchronous, but the caller can await it anyway!
return Task.FromResult(true);
}
类型Task<TResult>
要求您从任务中返回一个TResult
。如果没有任何要返回的内容,可以使用Task
(顺便说一下,它是Task<TResult>
的基类(。
但请记住,任务不是线程。任务是要完成的作业,而线程是工作线程。随着程序的运行,作业和工作人员变得可用和不可用。在后台,库会将您的作业分配给可用的工作人员,并且由于创建新的工作人员是一项成本高昂的操作,因此通常更喜欢通过线程池重用现有的工作人员。