C# Task.Factory.StartNew-won';不要等待任务完成?
我发现,如果使用该实现,以下代码实际上不会等待task client.SendAsync():C# Task.Factory.StartNew-won';不要等待任务完成?,c#,async-await,task-parallel-library,C#,Async Await,Task Parallel Library,我发现,如果使用该实现,以下代码实际上不会等待task client.SendAsync(): taskList.Add(Task.Factory.StartNew(() => new Program().Foo())); 如果我将其从Task.Factory.StartNew()更改为new Program().Foo()或Task.Run(()=>new Program.Foo()),它将正确地输出一些信息。两者之间的区别是什么 internal class Program {
taskList.Add(Task.Factory.StartNew(() => new Program().Foo()));
如果我将其从Task.Factory.StartNew()
更改为new Program().Foo()
或Task.Run(()=>new Program.Foo()
),它将正确地输出一些信息。两者之间的区别是什么
internal class Program
{
private async Task Foo()
{
while (true)
{
var client = new HttpClient();
var requestMessage = new HttpRequestMessage(HttpMethod.Head, "http://www.google.com");
HttpResponseMessage response = await client.SendAsync(requestMessage);
Console.WriteLine(response.RequestMessage.RequestUri.ToString());
}
}
private static void Main(string[] args)
{
var taskList = new List<Task>();
// This won't output anything.
taskList.Add(Task.Factory.StartNew(() => new Program().Foo()));
// This will.
taskList.Add(Task.Run(() => new Program().Foo()));
// So does this.
taskList.Add(new Program().Foo());
Task.WaitAll(taskList.ToArray());
}
}
您的代码使用语句
Task.WaitAll(taskList.ToArray());
但是,Foo
不会在返回之前等待client.SendAsync(requestMessage)
的结束,因为它有一个wait
。wait将允许方法返回任务
对象,并允许线程返回下一行
“问题”是,由于您返回了wait
,因此调用Foo
方法的任务在那时就完成了,甚至在您点击命令行上的输出之前(但是Foo
方法返回的任务还没有完成)
你基本上有3个“时间表”(我不说线程,因为我不确定HttpClient是否真的启动了一个新线程,但如果有人能确认这一点,我会编辑帖子)和2个任务:
- 你的
线程Main
- 使用
StartNew创建的任务
- 发送异步任务
taskList.Add(Task.Factory.StartNew(() => new Program().Foo().Wait()));
但是,再次强调,仅仅为了等待另一个任务而启动一个新任务没有多大意义,因此您最好使用
taskList.Add(new Program().Foo());
问题在于Task.Factory.StartNew
不是“任务感知”的。也就是说,从方法调用到StartNew
的返回类型实际上是一个任务
。这意味着您只等待外部任务完成,而不是内部任务完成
一个简单的解决方案是使用以下方法:
private static void Main(字符串[]args)
{
var taskList=新列表();
taskList.Add(Task.Factory.StartNew(()=>newprogram().Foo()).Unwrap());
Task.WaitAll(taskList.ToArray());
}
Task.Run
之所以有效,是因为它是“任务感知”的。它在内部为您调用Unwrap
,只返回内部任务。Task.Factory.StartNew默认情况下不等待内部任务完成。如果您创建了一个带有返回值的变量,您将得到以下结果:
Task<Task> task = Task.Factory.StartNew(() => new Program().Foo());
您发布的博客文章也解释了同步委托和异步委托之间的区别。主题行中问题的答案-不,除非您要求。请查看异步/等待模式。这将拓宽您在这个问题上的视野。@derekhh:Read。当您将操作传递给Task时,您引用的部分带有前缀。运行,这是您的代码没有做的。在博文的后面,他解释了Task.Run
如何与异步委托行为不同。对于单个任务:var Task=Task.Factory.StartNew(something);
Task.Wait();
private static void Main(string[] args)
{
var taskList = new List<Task>();
taskList.Add(Task.Factory.StartNew(() => new Program().Foo()).Unwrap());
Task.WaitAll(taskList.ToArray());
}
Task<Task> task = Task.Factory.StartNew(() => new Program().Foo());
Task task = Task.Factory.StartNew(() => new Program().Foo()).Unwrap();
taskList.Add(task);