简体   繁体   English

切换异步任务以同步任务

[英]Switch async Task to sync task

I have the following code: 我有以下代码:

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

Is it possible to convert ContinueWhenAll to a synchronous method? 是否可以将ContinueWhenAll转换为同步方法? I want to switch back between async and sync. 我想在异步和同步之间切换。

Edit: I should metnion that each of the "tasks" in the continuewhenall method should be executing synchronously. 编辑:我应该提到continuewhenall方法中的每个“任务”都应同步执行。

Unless am mistaken this is what you're looking for 除非弄错了,否则这就是您要寻找的

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

If you want to leave your existing code intact and have a variable option of executing synchronously you should make these changes: 如果您希望保持现有代码不变,并具有同步执行的可变选项,则应进行以下更改:

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();

This way you can toggle it programmatically instead of by editing your source code. 这样,您可以通过编程方式切换它,而无需编辑源代码。 And you can keep the continuation code the same for both methods. 您可以将两种方法的延续代码保持相同。

Edit: 编辑:

Here is a simple pattern for having the same method represented as a synchronous and async version: 这是用于将相同方法表示为同步和异步版本的简单模式:

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

public Task<Item> CreateItemAsync(string name)
{
    return Task.Factory.StartNew(() => CreateItem(name));
}

i think you can try this. 我想你可以试试看。

using TaskContinuationOptions for a simple scenario. 在一个简单的场景中使用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);

or using TPL Dataflow for a complex scenario. 或在复杂情况下使用TPL Dataflow

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM