Async / Await使用Task.Run异步启动新线程吗?

我已经阅读了很多文章,但仍然无法理解这一部分。

考虑以下代码:

private async void button1_Click(object sender, EventArgs e) { await Dosomething(); } private async Task Dosomething() { await Task.Run((() => "Do Work")); return "I am done"; } 

第一个问题:

当我单击按钮时,它将调用DoSomething并等待通过调用Task.Run(如果我没有记错)从线程池创建线程的任务,并且所有这些都以异步方式运行。 所以我实现了创建一个完成我的工作但是异步执行的线程? 但是考虑到我不需要任何结果,我只是希望在没有得到任何结果的情况下完成工作,是否真的需要使用async / await,如果是这样,怎么样?

第二个问题:

在异步运行线程时,它是如何工作的? 它是在主UI上运行但是在单独的线程上运行还是在单独的线程上运行并且在该方法中是异步的?

  1. 创建异步方法的目的是为了以后可以等待它们。 有点像“我要把这些水煮沸,完成准备其余的汤料,然后回到锅里等待水煮沸,这样我就可以做晚餐了。” 你开始水沸腾,它在你做其他事情时它是异步的,但最终你必须停下来等待它。 如果你想要的是“即发即忘”,那么就不需要Async和Await。

在C#中执行fire and forget方法的最简单方法是什么?

  1. 启动新任务会将该任务排队,以便在线程池线程上执行。 线程在进程的上下文中执行(例如,运行应用程序的可执行文件)。 如果这是在IIS下运行的Web应用程序,则该线程将在IIS工作进程的上下文中创建。 该线程与主执行线程分开执行,因此无论主执行线程在做什么,它都会关闭并执行其操作,同时,您的主执行线程继续自己的工作。

Task类型要求您从任务中返回TResult 。 如果您没有任何要返回的内容,则可以使用Task (顺便提一下,它是Task的基类)。

但请记住,任务不是一个线程。 任务是要完成的工作,而线程是工作者。 随着您的程序运行,作业和工作人员变得可用且不可用。 在幕后,图书馆会将您的工作分配给可用的工作人员,因为创建新工作人员是一项代价高昂的操作,所以通常更愿意通过线程池重用现有工作人员。

1

如果您没有await Taskawait它,那么会有很大的不同:

  • 如果您没有awaitDoSomething被调用但是在DoSomething Task尚未完成时执行下一句。

  • await它的情况DoSomething被调用,下一句话在DoSomething Task完成后执行。

因此, async / await的需要将取决于你想如何调用DoSomething :如果你不await它就像把它称为火与忘记方式

2

它是在主UI上运行但是在单独的线程上运行还是在单独的线程上运行并且在该方法中是异步的?

异步代码有时意味着其他线程 (请参阅此Q&A 异步与multithreading – 是否存在差异? )。 也就是说,如果代码是在与UI一个单独的线程中执行的,或者它允许在恢复时继续处理UI线程,这很好,因为UI循环仍然可以在其他任务完成时更新屏幕平行而不冻结UI。

异步方法(即async方法)是一种语法糖,用于告诉编译器应将await语句视为状态机。 C#编译器将您的async / await代码转换为状态机,等待Task结果的代码在等待的代码之后执行。

有趣的问答

您可能想要查看这些其他问答:

  • Async / Await vs Threads
  • Task.Start / Wait和Async / Await有什么区别?
  • async / await – 何时返回Task vs void?
  • Async等待关键字等同于ContinueWith lambda吗?

OP说……

[…]但这是否意味着“async / await”将触发一个线程,Task.Run也会触发一个线程,或者它们都是同一个线程?

使用asyncawait并不意味着“我创建一个线程” 。 以优雅的方式实现延续只是一种语法糖。 任务可能是也可能不是线程。 例如, Task.FromResult(true)创建一个假任务,以便能够实现异步方法而无需创建线程:

 public Task 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); }