c# - Task.Factory.StartNew 不会等待任务完成?

标签 c# async-await task-parallel-library

我发现如果我使用实现,下面的代码实际上不会等待任务 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/

相关文章:

c# - C# 应用程序可以与 Node.js 代码通信吗?

.net - Rx 框架中的什么允许我在创建期间等待其他方法时返回 IObservable<T> ?

.net - Parallel.For 多久调用一次 localInit?

c# - 如何为 TPL 中的任务分配名称

c# - 将字符串转换为 datetime2

c# - 如何使用 dbAutoTrack 使用 DrawTable

c# - Server.MapPath - 不允许加载本地资源错误

typescript - async lambda 在 typescript 和即将推出的 ecmascript 7 中是否合法?

scala - Future/Await 和 Async/Await 的区别是什么

javascript - 试图在 JS 中的数组中获取值,该数组位于函数外部且该函数是异步的