多个异步任务执行
本文关键字:执行 任务 异步 | 更新日期: 2023-09-27 18:01:11
请耐心等待:-(
我正在为c#中的TPL而挣扎,一直在努力找出设计一个解决方案的最佳方法,以启动多个异步任务,等待它们完成,然后继续前进。我的初始POC如下。每个IDataGatherer实例都需要获取数据并将其传递到DataObject实例中。
-
我不确定如何处理DownloadStringTaskAsync调用的延续,这样我就可以获得结果并将其传递到DataObject中。ContinueWith希望提供一个具有void返回签名的方法,但我觉得ExtractData方法需要返回一个Task实例,否则我没有从GetDataAsync((方法返回的Task实例。
-
我还想知道我是否需要在我的IDataGatherer实例中引入TaskCompletionSource,但我如何将其与正在进行实际工作的任务联系起来——例如DownloadstringTaskAsync和ExtractData?
interface IDataGatherer
{
Task<DataObject> GetDataAsync();
}
class DataObject
{
public string Data { get; set; }
}
class IpGatherer : IDataGatherer
{
private readonly string _url = "http://ip.jsontest.com";
public Task<DataObject> GetDataAsync()
{
var tcs = new TaskCompletionSource<DataObject>(); // Do I need this???
var client = new WebClient();
// stuck here
var task = client.DownloadStringTaskAsync(_url).ContinueWith(ExtractData);
}
private void ExtractData(Task<string> obj)
{
}
}
class Program
{
private static void Main(string[] args)
{
// takes a list of IDataGatherers and waits for them
// all to complete, handles exceptions, etc.
}
}
以这种方式设计解决方案可能会使事情过于复杂,所以我愿意接受清理或更简洁的建议。
我使用的是.NET 4.5
首先,您不需要TaskCompletionSource
。这是因为ContinueWith()
可以提供一个具有非void
签名的方法。例如:
public Task<DataObject> GetDataAsync()
{
var client = new WebClient();
return client.DownloadStringTaskAsync(_url)
.ContinueWith((Func<Task<string>, DataObject>)ExtractData);
}
private DataObject ExtractData(Task<string> task)
{
return new DataObject(task.Result);
}
(使用Result
不会阻塞,因为您可以确定Task
将在此时完成。(
但由于您使用的是DownloadStringTaskAsync()
,因此您可能使用的是.Net 4.5,这意味着您可以使用await
。这使得代码更加简单:
public async Task<DataObject> GetDataAsync()
{
var client = new WebClient();
var s = await client.DownloadStringTaskAsync(_url);
return ExtractData(s);
}
private DataObject ExtractData(string s)
{
return new DataObject(s);
}