2

次のコードがあります。

Task.Factory.ContinueWhenAll(items.Select(p =>
{
    return CreateItem(p);
}).ToArray(), completedTasks => { Console.WriteLine("completed"); });

ContinueWhenAll同期メソッドに変換することは可能ですか? 非同期と同期を元に戻したい。

編集:continuewhenallメソッドの各「タスク」は同期的に実行する必要があることに注意してください。

4

3 に答える 3

1

これを試すことができると思います。

単純なシナリオではTaskContinuationOptionsを使用します。

var taskFactory = new TaskFactory(TaskScheduler.Defau

var random = new Random();
var tasks = Enumerable.Range(1, 30).Select(p => {
    return taskFactory.StartNew(() => {
        var timeout = random.Next(5, p * 50);
        Thread.Sleep(timeout / 2);
        Console.WriteLine(@"  1: ID = " + p);
        return p;
    }).ContinueWith(t => {
        Console.WriteLine(@"* 2: ID = " + t.Result);
    }, TaskContinuationOptions.ExecuteSynchronously);
}).ToArray();

Task.WaitAll(tasks);

複雑なシナリオではTPL データフローを使用します。

var step2 = new ActionBlock<int>(i => {
    Thread.Sleep(i);
    Console.WriteLine(@"* 2: ID = " + i);
}, new ExecutionDataflowBlockOptions {
    MaxDegreeOfParallelism = 1,
    //MaxMessagesPerTask = 1
});

var random = new Random();
var tasks = Enumerable.Range(1, 50).Select(p => {
    return Task.Factory.StartNew(() => {
        var timeout = random.Next(5, p * 50);
        Thread.Sleep(timeout / 2);
        Console.WriteLine(@"  1: ID = " + p);
        return p;
    }).ContinueWith(t => {
        Thread.Sleep(t.Result);
        step2.Post(t.Result);
    });
}).ToArray();

await Task.WhenAll(tasks).ContinueWith(t => step2.Complete());
await step2.Completion;
于 2015-01-19T06:51:05.960 に答える
1

既存のコードをそのまま残し、同期的に実行する可変オプションを使用する場合は、次の変更を行う必要があります。

bool isAsync = false; // some flag to check for async operation

var batch = Task.Factory.ContinueWhenAll(items.Select(p =>
{
    return CreateItem(p);
}).ToArray(), completedTasks => { Console.WriteLine("completed"); });

if (!isAsync)
    batch.Wait();

このようにして、ソース コードを編集する代わりにプログラムで切り替えることができます。また、両方のメソッドで継続コードを同じに保つことができます。

編集:

以下は、同じメソッドを同期バージョンと非同期バージョンとして表す単純なパターンです。

public Item CreateItem(string name)
{
    return new Item(name);
}

public Task<Item> CreateItemAsync(string name)
{
    return Task.Factory.StartNew(() => CreateItem(name));
}
于 2013-10-18T19:03:39.187 に答える