在下面的代码中,我想同步任务列表的结果报告。这是因为task.Result阻塞,直到任务完成。但是,任务ID = 3需要很长时间才能完成,并阻止所有其他已完成的任务报告其状态。没有UI线程的任务同步
我认为我可以通过将报告(Console.Write)移动到.ContinueWith指令中,但我没有UI线程,因此如何获取TaskScheduler来同步.ContinueWith任务?
我现在拥有的一切:
static void Main(string[] args)
{
Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);
var tasks = new List<Task<int>>();
for (var i = 0; i < 10; i++)
{
var num = i;
var t = Task<int>.Factory.StartNew(() =>
{
if (num == 3)
{
Thread.Sleep(20000);
}
Thread.Sleep(new Random(num).Next(1000, 5000));
Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
return num;
});
tasks.Add(t);
}
foreach (var task in tasks)
{
Console.WriteLine("Completed {0} on {1}", task.Result, Thread.CurrentThread.ManagedThreadId);
}
Console.WriteLine("End of Main");
Console.ReadKey();
}
我想移动到这个或类似的东西,但我需要的Console.Write(“已完成...”),以一切发生在同一线程上:
static void Main(string[] args)
{
Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);
for (var i = 0; i < 10; i++)
{
var num = i;
Task<int>.Factory.StartNew(() =>
{
if (num == 3)
{
Thread.Sleep(20000);
}
Thread.Sleep(new Random(num).Next(1000, 10000));
Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
return num;
}).ContinueWith(value =>
{
Console.WriteLine("Completed {0} on {1}", value.Result, Thread.CurrentThread.ManagedThreadId);
}
/* need syncronization context */);
}
Console.WriteLine("End of Main");
Console.ReadKey();
}
- 解决方案 - 得到一些意见和阅读部分的解决方案,这是完整的解决方案,我想要做什么之后。这里的目标是尽可能快地处理长时间运行的任务,然后对每个任务的结果进行一次处理。
static void Main(string[] args)
{
Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);
var results = new BlockingCollection<int>();
Task.Factory.StartNew(() =>
{
while (!results.IsCompleted)
{
try
{
var x = results.Take();
Console.WriteLine("Completed {0} on {1}", x, Thread.CurrentThread.ManagedThreadId);
}
catch (InvalidOperationException)
{
}
}
Console.WriteLine("\r\nNo more items to take.");
});
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
{
var num = i;
var t = Task.Factory.StartNew(() =>
{
if (num == 3)
{
Thread.Sleep(20000);
}
Thread.Sleep(new Random(num).Next(1000, 10000));
Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
results.Add(num);
});
tasks.Add(t);
}
Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => results.CompleteAdding());
Console.WriteLine("End of Main");
Console.ReadKey();
}
我假设控制台线程是一个替身的GUI(的WinForms/WPF)。这不是一个好主意,Dispatcher/Messageloop的存在会造成(很大的)差异。 –
否则,请思考“在同一个线程上发生的事情”。除非该线程正在轮询,否则不能这样做。 –
我需要对其进行更改,以便一次只运行一个ContinueWith任务。不管他们是否在同一个线程上运行,但我不能让他们中的两个并行运行。在现实生活中,ContinueWith部分将大量数据写入数据库。 –