多个任务并行启动,每个任务都有自己的超时时间 [英] Parallel start of several tasks, each of which has its own timeout

查看:35
本文介绍了多个任务并行启动,每个任务都有自己的超时时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个类似的任务,每个任务都有超时限制,即必须比指定时间完成得更快或返回空结果.这些任务的主要目的是从具有超时限制的服务器接收响应.此类任务的示例如下:

I have several similar tasks, each of which is limited to a timeout, i.e. must be completed faster than the specified time or return an empty result. The main purpose of these tasks is receiving a response from the server with a timeout limit. An example of such task is below:

       public async Task<List<Data>> GetDataWithTimeoutAsync(InputData data, int timeout)
        {   
            List<Data> resultData = new List<Data>;
            await Task.WhenAny(Task.Run(async () =>
                {
                    resultData.Add(SomeWork(data));
                }),
                Task.Delay(timeout));

            return resultData;
        }

这些任务中的每一个都可以单独正常工作.

Each of these tasks works correctly separately.

但我想并行运行一些这样的任务.为此,我使用以下代码.

But I want to run some of such tasks in parallel. For this, I use the following code.

        public async Task<List<List<Data>>> GetAllDataAsync()
        {
            var resultTasks = new ConcurrentBag<Task<List<Data>>>();

            var firtsTask = GetDataWithTimeoutAsync(firstInputData, firtsTimeout);
            var secondTask = GetDataWithTimeoutAsync(secondInputData, secondTimeout);
            var thirdTask = GetDataWithTimeoutAsync(thirdInputData, thirdTimeout);

            resultTasks.Add(Task.Run(() => firtsTask));
            resultTasks.Add(Task.Run(() => secondTask));
            resultTasks.Add(Task.Run(() => thirdTask));

            await Task.WhenAll(resultTasks);

            var result = resultTasks.Select(t => t.Result).ToList();

            return result;

        }

但是如果为嵌套任务设置了不同的超时,则此代码将无法正常工作.在这种情况下,所有任务都在最小的超时后完成.

But this code works incorrectly if different timeouts are set for nested tasks. In this case all of tasks are completed after the smallest of the timeouts.

如果每个任务都是 WhenAny 的结果,我如何与 WhenAll 并行运行一些任务?

How i can run some tasks in parallel with WhenAll if each of task is a result of WhenAny?

推荐答案

你的代码无法编译,所以我写了类似的东西.我无法重现您的结果.在我的情况下,具有不同超时的 WhenAll 按预期工作.当运行时间最长的任务完成时,它完成,这是第二个(200 毫秒).

Your code doesn't compile, so I wrote something similar. I can't reproduce your results. In my case the WhenAll with different timeouts works as expected. It completes when the longest running task is completed, which is the second one (200 msec).

public static async Task Main(string[] args)
{
    var task1 = GetDataAsync(100).WithTimeout(50);  // Should timeout after 50 msec
    var task2 = GetDataAsync(200).WithTimeout(300); // Should complete after 200 msec
    var task3 = GetDataAsync(300).WithTimeout(100); // Should timeout after 100 msec
    var stopwatch = Stopwatch.StartNew();
    var results = await Task.WhenAll(task1, task2, task3); // Wait for all
    stopwatch.Stop();
    Console.WriteLine($"Results: {String.Join(", ", results)}");
    Console.WriteLine($"Elapsed: {stopwatch.ElapsedMilliseconds} msec");
}

private static async Task<int> GetDataAsync(int input) // the input is used as delay
{
    await Task.Delay(input);
    return input;
}

public static Task<T> WithTimeout<T>(this Task<T> task, int timeout)
{
    var delayTask = Task.Delay(timeout).ContinueWith(_ => default(T),
        TaskContinuationOptions.ExecuteSynchronously);
    return Task.WhenAny(task, delayTask).Unwrap();
}

输出:

Results: 0, 200, 0
Elapsed: 211 msec

这篇关于多个任务并行启动,每个任务都有自己的超时时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆