【发布时间】:2014-09-17 04:40:29
【问题描述】:
我想知道如何以“正确”的方式编写自己的异步方法。
我看过很多这样解释异步/等待模式的帖子:
http://msdn.microsoft.com/en-us/library/hh191443.aspx
// Three things to note in the signature:
// - The method has an async modifier.
// - The return type is Task or Task<T>. (See "Return Types" section.)
// Here, it is Task<int> because the return statement returns an integer.
// - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
private void DoIndependentWork()
{
resultsTextBox.Text += "Working........\r\n";
}
这适用于任何已经实现此功能的 .NET 方法,例如
- System.IO 操作
- 数据库操作
- 网络相关操作(下载、上传...)
但是,如果我想编写我自己的方法,该方法需要相当长的时间才能完成,而我没有可以使用的方法,并且上面示例的 DoIndependentWork 方法中的负载很重,该怎么办?
我可以这样做:
- 字符串操作
- 计算
- 处理我自己的对象
- 聚合、比较、过滤、分组、处理资料
- 列出操作、添加、删除、应对
我又一次偶然发现了许多帖子,人们只是执行以下操作(再次以上面的示例为例):
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
await DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
private Task DoIndependentWork()
{
return Task.Run(() => {
//String manipulations
//Calculations
//Handling my own objects
//Aggregating, comparing, filtering, grouping, handling stuff
//List operations, adding, removing, coping
});
}
您可能会注意到更改是DoIndependentWork 现在返回一个任务,而在AccessTheWebAsync 任务中,该方法得到了一个await。
重负载操作现在被封装在Task.Run() 中,这就是全部吗?
如果这就是我需要做的唯一事情,我需要为我的库中的每个方法提供异步方法,如下:
public class FooMagic
{
public void DoSomeMagic()
{
//Do some synchron magic...
}
public Task DoSomeMagicAsync()
{
//Do some async magic... ?!?
return Task.Run(() => { DoSomeMagic(); });
}
}
如果您能向我解释一下,那就太好了,因为即使是这样一个高票数的问题: How to write simple async method? 仅使用现有方法对其进行解释,并且仅使用 asyn/await 模式,如上述问题的评论将其引向重点: How to write simple async method?
【问题讨论】:
-
我可能有点跑题了,但
resultsTextBox.Text += "Working........\r\n";还能用吗?这在无 GUI 线程中运行,因此您需要调用,对吗?谢谢。 -
@Kimmax 不确定 - 仍在努力解决这个问题,但我目前的印象是
async签名会在幕后添加编组,或者可能只有当你await某事? -
@CodeJockey 感谢您从死里复活这个评论:P 同时我确实了解更多并且知道使用类似
Progress.Report和数据绑定的东西可以完全解决这个问题。 -
好问题,我一直想知道完全相同的事情,但没有找到任何好的例子。最佳答案有助于澄清一些事情,但就像您一样,我希望从该答案中获得更多信息。
标签: c# .net asynchronous task-parallel-library async-await