继续不射击 [英] ContinueWith not firing

查看:61
本文介绍了继续不射击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

.Net 4.5.1. x64 Win2008R2

.Net 4.5.1. x64 Win2008R2

我遇到的情况是,对于给定的任务集合,任务系统陷入了僵局.总体上看起来像这样

I have a situation were it seems the task system is deadlocked for a given collection of tasks. At a high level it looks like this

var completion = CreateTask();

completion.ContinueWith(async t => { await Log("I'm done").ConfigureAwait(false); }, TaskScheduler.Default);

completion.ContinueWith(completion =>
{
	Task.Delay(TimeSpan.FromMinutes(5)).ContinueWith(timeout =>
	{
		await Log("I failed").ConfigureAwait(false);
	}, TaskScheduler.Default);
	try { source.Cancel(); } catch { }
}, CancellationToken.None, TaskContinuationOptions.NotOnRanToCompletion, TaskScheduler.Default);

await completion.ConfigureAwait(false); //Never runs

几乎所有时间我都做完"和我失败"运行并等待完成都完成.但是有时当系统承受非常重的负载时,只有我完成了".正常工作,我失败了"永远不会发生,然后等待" 完成"永远不会结束.

Nearly all of the time "I'm done" and "I failed" both run and await completion completes. But sometimes when the system is under very heavy load, only "I'm done" works and "I failed" never happens and "await completion" never finishes.

此问题的更详细版本是

using(var cancelSource = new CancellationTokenSource) { var tasks = List<Task>(); foreach(var config in configs) { var work = new Thing(config, cancelSource.token); tasks.add(work.Completion); } var tcs = new TaskCompletionSource(); foreach(var completion in tasks) { completion.ContinueWith(async t => { await Log("I'm done").ConfigureAwait(false); }, TaskScheduler.Default);

completion.ContinueWith(async t => {await Log(我没有完成").ConfigureAwait(false);},CancellationToken.None,TaskContinuationOptions.NotOnRanToCompletion,TaskScheduler.Default);

completion.ContinueWith(async t => { await Log("I didn't finish").ConfigureAwait(false); }, CancellationToken.None, TaskContinuationOptions.NotOnRanToCompletion, TaskScheduler.Default);

complete.ContinueWith(completion => { Task.Delay(TimeSpan.FromMinutes(5)).ContinueWith(timeout => { tcs.TrySetException(new TimeoutException(任务花费太长时间才能取消"))); },TaskScheduler.Default); 尝试{cancelSource.Cancel(); } 抓住 { } },CancellationToken.None,TaskContinuationOptions.NotOnRanToCompletion,TaskScheduler.Default); } 等待Task.WhenAny(tcs.Task,Task.WhenAll(tasks)).ConfigureAwait(false); //在一个或多个任务失败的某些情况下,永远不会完成 }

completion.ContinueWith(completion => { Task.Delay(TimeSpan.FromMinutes(5)).ContinueWith(timeout => { tcs.TrySetException(new TimeoutException("tasks took too long to cancel")); }, TaskScheduler.Default); try { cancelSource.Cancel(); } catch { } }, CancellationToken.None, TaskContinuationOptions.NotOnRanToCompletion, TaskScheduler.Default); } await Task.WhenAny(tcs.Task, Task.WhenAll(tasks)).ConfigureAwait(false); //Never finishes in some cases where one or more tasks fail }

我将看到一堆我已经完成"和我还没有完成",但是"WhenAny"永不结束". TaskCompletionSource的原因是要处理某些取消逻辑中存在错误的情况 工作已经完成,我们只需要这组工作就可以结束.


I will see a bunch of "I'm done"'s and "I didn't finish"s, but the "WhenAny" never finishes". The reason for the TaskCompletionSource is to handle situations where there is a bug in the cancellation logic of some work being done and we just need this group of work to just end.


推荐答案

您好

Hi Benjie2525,

抱歉,由于新年假期,我迟到了.

Sorry for my late reply because of a new year holiday.

我尝试根据您的代码重现您的问题,但是很抱歉,我无法使用某些未定义的参数.我建议您提供一个简化的演示,以帮助我找出根本原因.

I try to reproduce your issue based on your code, but sorry I am failed with some undefined parameters. I would suggest you provide a simplified demo to help me figure out the root cause.

在这里,我还创建了一个小演示.

Here I also created a small demo.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MultiThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Test2();
            Console.Read();
        }

        public async static void Test2()
        {
            Task<int> t = new Task<int>(n => Sum((int)n),1000);
            t.Start();
            Task cwt = t.ContinueWith(task => Console.WriteLine("The sum is" + task.Result));
            Task tt = t.ContinueWith(async ttt => { await ttt.ConfigureAwait(false); }, TaskScheduler.Default);
        
            await t.ConfigureAwait(false);
        }

        private static int Sum(int n)
        {
            int sum=0;
            for(int i=0;i<=n;i++)
            {
                sum += i;
                Console.WriteLine(sum);
            }
            return sum;
        }

    }
}

这是我的屏幕截图,在我这边效果很好,请看一下

Here is my screen capture, it works fine on my side, please have a look

它符合您的要求吗?如果没有,我仍然建议您在此处重新发布已执行的演示,我将作进一步的研究.

Does it meet your requirement? If not, I still suggest you repost an executed demo here, I will take a further look.

祝你有美好的一天!

克里斯汀


这篇关于继续不射击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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