了解异步方法

时间:2014-09-11 10:34:22

标签: c# asynchronous async-await

我有一个方法void getInformation(),它调用其他五种方法,每种方法都从数据库中获取一些数据。在收集所有数据并返回getInformation()之前大约需要1秒钟,因此我认为我应该在后台收集数据。我的问题是:我可以制作getInformation() async,以便在其他方法收集信息时阻止用户界面,或者我是否必须制作其他所有方法async

private void button_Click(object sender, EventArgs e)
{
  await getContactInformation();
}

public async Task getContactInformation()
{
  this.data.Add(collectData1());
  this.data.Add(collectData2());
  this.data.Add(collectData3());
  this.data.Add(collectData4());
  this.data.Add(collectData5());
}

5 个答案:

答案 0 :(得分:2)

一般情况下,我建议将所有IO从UI线程中删除,但是每个人调用async都没有意义。

关于async调用对数据库IO阻塞线程的影响的指导,我发现了这个非常明确和有用的建议。

http://blogs.msdn.com/b/rickandy/archive/2009/11/14/should-my-database-calls-be-asynchronous.aspx

答案 1 :(得分:2)

没有。你的方法体必须使用await,否则你会收到警告。

很容易。

用...包裹你的方法体

await Task.Run(()=>{
// do your thing
});

答案 2 :(得分:2)

首先,async的理想情况是一直使用" async"。在这种情况下,您的代码将如下所示:

private async void button_Click(object sender, EventArgs e)
{
  await getContactInformationAsync();
}

public async Task getContactInformationAsync()
{
  this.data.Add(await collectData1Async());
  this.data.Add(await collectData2Async());
  this.data.Add(await collectData3Async());
  this.data.Add(await collectData4Async());
  this.data.Add(await collectData5Async());
}

请注意,现代数据库API(如Entity Framework 6,ADO.NET,SQLite等)都具有可用于实现collectDataNAsync方法的异步API。这是理想的async场景,因为它可以最大限度地减少线程浪费,并使UI保持良好的响应能力。

但是,如果你想要更多的"快速修复",那么你可以将(同步)调用推送到后台线程,然后异步处理该后台工作,如下:

private async void button_Click(object sender, EventArgs e)
{
  await Task.Run(() => getContactInformation());
}

public void getContactInformation()
{
  this.data.Add(collectData1());
  this.data.Add(collectData2());
  this.data.Add(collectData3());
  this.data.Add(collectData4());
  this.data.Add(collectData5());
}

这将以牺牲线程池线程为代价解决您的直接问题(释放UI线程)。它不是理想但它会起作用。

答案 3 :(得分:1)

异步任务的目的是让它在后台执行而不锁定主线程,例如执行DownloadFileAsync。 基本思想是您有一个单独的线程池,可以异步执行任务。使用时。但是,该对象确实会在某个时间执行操作并在您请求时为您提供结果。这意味着它会在您请求结果时阻塞但尚未完成,但在线程池中执行。

异步和同步之间的唯一区别是我们可以在异步方法启动后执行某些操作(例如编写消息)。它避免了阻塞控制流程。声明继续正常进行。 Async和await是一种代码模式 - 它们允许方法异步运行。它们使得使用线程的代码更容易阅读。而这反过来又使代码不易出现缺陷。

http://blogs.msdn.com/b/cdndevs/archive/2013/12/18/c-async-and-await-why-do-we-need-them-part-1.aspx

How and When to use `async` and `await`

<强>最后

程序中充满了不会立即返回的方法。有时外部放缓,如网络,是原因, 不是处理器用法。使用async和await,我们以异步方式运行方法 - 线程是可选的。

答案 4 :(得分:1)

  

我可以只使getInformation()异步,这样在其他方法收集信息时不阻止UI,或者我是否必须使其他每个方法都异步?

后者。当你去async时,“一直是异步”,这意味着你可以一直调用到堆栈顶部的async方法调用。对于IO绑定操作,不需要使用后台线程,因为现在大多数API都会公开XXXAsync方法调用,这些方法调用是真正异步的,这意味着您的UI消息循环可以在IO请求时自由处理其他消息执行。

需要注意的一点是,标记方法async不足以使其异步。实际上,您必须await进行异步操作,例如数据库方法调用。如果没有对数据库的异步API调用,则无法进行异步。

在这种情况下,getContactInformation会使编译器省略一条警告,说明你有一个不等待的异步方法。事实上,如果你await getInformation(),你将完全同步运行。