线程vs begininvoke vs async

时间:2013-10-29 00:06:25

标签: multithreading delegates async-await

我是线程和异步编程的新手。我正在努力学习这些概念,到目前为止我理解它,但有一个问题要问。

假设我想调用一个名为GetAllUsers()的方法,这种方法需要很长时间才能执行,因为它不会阻止资源并保持UI响应。所以,我的理解是它可以通过3种方式完成(如果这些方法正确或我完全弄错了,请告诉我): -

1)线程:我可以生成一个新线程并将GetAllUsers方法作为线程启动。这将开始在不同的线程上执行该方法,保持我的ui响应,并且当调用完成时,我可以使用路由技术来更新UI控件,即InvokeRequired。我的理解是否正确?

2)异步代理:我可以创建一个委托。创建它的新实例并将其指向方法GetAllUsers。然后使用BeginInvoke方法。引擎盖下的BeginInvoke将生成一个新线程并运行我的方法,保持UI响应。调用完成后,将调用回调方法,并再次使用路由技术更新GUI线程上的控件。我的理解是否正确?

或者

3)异步/等待:将外部方法标记为异步,并将方法GetAllUsers的调用标记为等待。这也将保持UI响应,因为运行它的线程可以跳出并执行一些其他工作,直到调用此慢速方法完成。我的理解是否正确?

现在,问题是 - 如果你阅读下面链接的第二段,它说async / await不会导致创建额外的线程。那么async / await如何设法提供与上面第一个2solution相同的输出而不创建任何额外的线程。解决方案1和2将导致多线程,但异步解决方案将不会。 async / await如何在引擎盖下工作。?

http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx#BKMK_Threads

1 个答案:

答案 0 :(得分:12)

  

我的理解是否正确?

是的,您的理解是正确的。

  

现在,问题是 - 如果你阅读下面链接的第二段,它说async / await不会导致创建额外的线程。那么async / await如何设法提供与上面第一个2solution相同的输出而不创建任何额外的线程

async修饰符和await运算符不必须创建新线程。执行异步的实际机制由您调用await的类型处理。如果您使用await Task.Run(() => YourMethod());,则Task.Run 使用线程池线程来执行操作。

但是,如果您可以重做方法以使GetAllUsers使用异步IO调用而不使用线程,那么await将不需要使用线程进行异步。例如,如果GetAllUsers花费大部分时间等待从服务器下载,则使用异步Web API将允许您在不使用额外线程的情况下使该方法异步。

在这种情况下,即使您必须将Task.Runawait一起使用,这里也有一个很好的优势 - 您可以修改您的方法以使用await,而不是陷入困境它的逻辑控制流程,保持异常处理干净,而不必担心使用BeginInvoke推回到UI线程 - 使用await,所有这些“混乱”都会为你处理,并且您的代码可以保持非常接近原始的非异步代码。