多个异步任务执行

时间:2013-02-26 20:14:22

标签: c# .net task-parallel-library

请耐心等待: - )

我正在努力解决c#中的TPL问题,并试图找出设计解决方案的最佳方法,以启动多个异步任务,等待它们完成并继续前进。我最初的POC在下面。每个IDataGatherer实例都需要获取数据并将其按摩到DataObject实例中。

  1. 我不确定如何处理DownloadStringTaskAsync调用的延续,这样我就可以获取结果并将其按下到DataObject中。 ContinueWith希望提供一个带有void返回签名的方法,但我觉得ExtractData方法需要返回一个Task实例,否则我没有从GetDataAsync()方法返回的Task实例。

  2. 我也想知道我是否需要在我的IDataGatherer实例中引入一个TaskCompletionSource,但是如何将其与正在进行实际工作的任务相提并论呢?例如,以下来关于StringtringTaskAsync和ExtractData?

  3. 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

1 个答案:

答案 0 :(得分:2)

首先,您不需要TaskCompletionSource。这是因为ContinueWith() 可以提供非void签名的方法。 E.g:

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);
}
相关问题