0

いくつかの大きな仕事をするいくつかのメソッドがあると仮定します。

最初は、メソッドがいくつあるかわかりません(1にすることも、10にすることもできます)。

コードでは、これは次のようになります。

public interface IWorker
{
    void DoWork(DataContainer data);
}

そして、このインターフェースを実装するいくつかのクラス。次に、インスタンスのリストがあります。

List<IWorker> workers = new List<IWorker>();

これらのメソッドを非同期で実行したいと思います。さらに、それらすべてが実行されたときにコールバックが必要です。

public void Callback()
{
    Console.WriteLine("everything done");
}

カスタムラッパーなどを作成せずにこれを行う方法はありますか?ThreadPool、Tasks、Parallelを使用しますか?

私が知っているように、Parrallelはタスクが完了するまでスレッドをブロックするので、これは好ましい動作ではありません。

タスクを作成するとき、私が見たようにパラメータのないメソッドがあるはずなので、これも良くありません。

ThreadPoolでは、メソッドQueueUserWorkItemを使用する可能性がありますが、このメソッドを使用すると、単一の「合計完了」コールバックを取得できません。

もちろん、ThreadPoolを使用して目的の機能を実装する独自のラッパーを作成することもできますが、目標は、そのような機能を記述せずにこれを作成することです。

誰か助けてもらえますか?ありがとう。

4

3 に答える 3

3

TaskTPL とクラスを探しています。

for each 操作を作成し、Task呼び出しTask.WhenAllて集計タスクを取得する

于 2013-03-03T20:05:58.410 に答える
1

Task.WhenAll を探しています。やりたいことを実行する一連のタスクを作成し、すべてのタスクを待機して、コールバックを続行します。DoWork メソッドの非同期バージョンを分割します。常に非同期で呼び出す場合は、必ずしもそうする必要はありません。

public interface IWorker
{
    Task DoWorkAsync(string data);
    void DoWork(string data);
}

public class Worker : IWorker
{
    public Task DoWorkAsync(string data)
    {
        return Task.Run(() => DoWork(data));
    }

    public void DoWork(string data)
    {
        Console.WriteLine(data);
        Thread.Sleep(100);
    }
}

public class Runner
{
    public void Callback()
    {
        Console.WriteLine("Everything done");
    }

    public void Run()
    {
        var workers = new List<IWorker> {new Worker(), new Worker(), new Worker()};
        var tasks = workers.Select(t => t.DoWorkAsync("some data"));

        Task.WhenAll(tasks).ContinueWith(task => Callback());

        Console.WriteLine("Waiting");
    }
}
于 2013-03-03T20:18:44.117 に答える
0

CountdownEventクラスの最有力候補のように思えます。

List<IWorker> workers = new List<IWorker>();
using (CountdownEvent e = new CountdownEvent(workers.Count))
{
    foreach (IWorker worker in workers)
    {
        // Dynamically increment signal count.
        e.AddCount();
        // run work itself on another thread
        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            try
            {
                ((IWorker)state[0]).DoWork((DataContainer)state[1]);
            }
            finally
            {
                e.Signal();
            }
        },
        // pass required parameters for block of work
        new object[] { worker, dataForWorker });
    }

    // wait for all workers to finish
    e.Wait();
    // run callback code
}
于 2013-03-03T20:14:48.363 に答える