Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/408.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Task.Factory.StartNew-won';不要等待任务完成?_C#_Async Await_Task Parallel Library - Fatal编程技术网

C# Task.Factory.StartNew-won';不要等待任务完成?

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 {

我发现,如果使用该实现,以下代码实际上不会等待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
{
    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创建的任务
  • 发送异步任务
您的<代码>主< /COD>线程正在等待由<代码> StestNux<代码>创建的任务的结束,但该任务“<强> > <强> >等待<代码> SDENASYNC CALL的结束,因此不等待命令行输出将其视为已完成。因为只有在<代码> WaitAll < /代码>中考虑到该命令。SendAsync不是,它提前返回是正常的

要有你想要的行为,你应该有

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);