切换异步任务以同步任务

时间:2013-10-18 18:44:29

标签: c# asynchronous

我有以下代码:

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

是否可以将ContinueWhenAll转换为同步方法?我想在异步和同步之间切换回来。

编辑:我应该知道,continuewhenall方法中的每个“任务”都应该同步执行。

3 个答案:

答案 0 :(得分:1)

除非你弄错了,否则这就是你要找的东西

Task.WaitAll(tasks);
//continuation code here

答案 1 :(得分: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));
}

答案 2 :(得分: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;