【发布时间】:2014-03-28 07:21:31
【问题描述】:
背景:
我有一个控制台应用程序,它创建 Tasks 来处理来自数据库的数据(我们称它们为 Level1 任务)。每个任务都会再次创建自己的任务来处理分配给它的数据的每一部分(2 级任务)。
每个 Level2 任务都有一个与之关联的延续任务,以及用于在继续之前对延续任务执行 WaitAll 的代码。
我在.NET 4.0(没有async/await)
问题:
这产生了一个问题——事实证明,如果以这种方式完成,在所有可用的 Level1 任务都安排好之前,没有任何 Level2 任务被启动。这无论如何都不是最佳的。
问题:
这似乎已通过更改代码以等待原始 Level2 任务及其继续任务来解决。但是,我不完全确定为什么会这样。
你有什么想法吗?
我唯一能想到的是 - 由于延续任务尚未开始,等待它完成是没有意义的。但即使是这样,我也希望至少有一些 Level2 任务已经开始。他们从来没有这样做过。
示例:
我创建了一个示例控制台应用程序来准确展示该行为:
按原样运行它,您会看到它首先安排所有任务,然后您才开始从 Level2 任务中获取实际写入的行。
但注释掉标记的代码块并取消注释替换,一切正常。
你能告诉我为什么吗?
public class Program
{
static void Main(string[] args)
{
for (var i = 0; i < 100; i++)
{
Task.Factory.StartNew(() => SomeMethod());
//Thread.Sleep(1000);
}
Console.ReadLine();
}
private static void SomeMethod()
{
var numbers = new List<int>();
for (var i = 0; i < 10; i++)
{
numbers.Add(i);
}
var tasks = new List<Task>();
foreach (var number in numbers)
{
Console.WriteLine("Before start task");
var numberSafe = number;
/* Code to be replaced START */
var nextTask = Task.Factory.StartNew(() =>
{
Console.WriteLine("Got number: {0}", numberSafe);
})
.ContinueWith(task =>
{
Console.WriteLine("Continuation {0}", task.Id);
});
tasks.Add(nextTask);
/* Code to be replaced END */
/* Replacement START */
//var originalTask = Task.Factory.StartNew(() =>
//{
// Console.WriteLine("Got number: {0}", numberSafe);
//});
//var contTask = originalTask
// .ContinueWith(task =>
// {
// Console.WriteLine("Continuation {0}", task.Id);
// });
//tasks.Add(originalTask);
//tasks.Add(contTask);
/* Replacement END */
}
Task.WaitAll(tasks.ToArray());
}
}
【问题讨论】:
-
一定要用
ContinueWith,还是可以用async/await? -
@Noseratio - 它是 .NET 4.0 - 没有异步/等待
-
如果您使用 VS2012+,您仍然可以将它用于 .NET 4.0:stackoverflow.com/tags/async-await/info
-
@Noseratio - VS 2010 恐怕
-
那么你的代码真的必须完全重构,这可能会有所帮助:blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx
标签: c# .net multithreading task-parallel-library