我发现如果我使用实现,下面的代码实际上不会等待任务 client.SendAsync():
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());
}
}
基于 this MSDN article ,似乎 Task.Run(someAction);
等同于 Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
/p>
但是即使我把代码改成这样,它也不会输出任何东西。为什么?
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>();
taskList.Add(Task.Factory.StartNew(() => new Program().Foo(), CancellationToken.None,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
//taskList.Add(Task.Run(() => new Program().Foo()));
//taskList.Add(new Program().Foo());
Task.WaitAll(taskList.ToArray());
}
}
最佳答案
问题在于 Task.Factory.StartNew
不是“任务意识”。意思是,您的方法调用的返回类型 StartNew
实际上是一个 Task<Task>
.这意味着您只是在等待完成外部任务,而不是内部任务。
一个简单的解决方案是使用 TaskExtensions.Unwrap()
方法:
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.Run
确实有效,因为它是“任务意识”。 It has an overload taking a Func<Task>
,内部调用 Unwrap
对你来说,只返回内部任务。
关于c# - Task.Factory.StartNew 不会等待任务完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33009656/