0

我慢してください:-)

私は C# で TPL に苦労しており、複数の非同期タスクを開始し、それらが完了するのを待ってから先に進むためのソリューションを設計するための最良の方法を見つけようとして立ち往生しています。私の最初の POC は以下のとおりです。各 IDataGatherer インスタンスは、データを取得して DataObject インスタンスに変換する必要があります。

  1. DownloadStringTaskAsync 呼び出しからの継続を処理して、結果を取得して DataObject に変換する方法がわかりません。ContinueWith は void リターン シグネチャを持つメソッドを提供したいと考えていますが、ExtractData メソッドが Task インスタンスを返す必要があるように感じます。そうしないと、GetDataAsync() メソッドから返す Task インスタンスがありません。

  2. 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を使用しています

4

1 に答える 1

2

まず、必要ありません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 を使用している可能性があります。つまり、.NET を使用できます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);
}
于 2013-02-26T20:58:53.763 に答える