为什么在静态构造函数中启动并等待一个空的.net任务时不会完成?

本文关键字:任务 net 一个 构造函数 静态 启动 等待 为什么 | 更新日期: 2023-09-27 18:18:27

我不明白为什么下面的代码不能工作:

var task = new Task(() => { });
task.Start();
if (task.Wait(10000))
{
   logger.Info("Works");
}
else
{  
   logger.Info("Doesn't work");
}

超时后,任务状态停留在"Running",尽管没有什么可做的。用task.RunSynchronously()代替task.Start()也可以。

有人知道我可能做错了什么吗?

复制这个问题的测试项目可以在这里找到:http://erwinmayer.com/dl/TaskTestProject.zip。据我所知,如果上面代码的方法在静态构造函数中运行,它将不起作用。但是,如果作为静态类方法直接调用,它可以工作。

最近的MSDN博客文章似乎强调了与静态构造函数相关的问题:http://blogs.msdn.com/b/pfxteam/archive/2011/05/03/10159682.aspx

为什么在静态构造函数中启动并等待一个空的.net任务时不会完成?

上下文在这里非常重要。当你像这样启动一个任务时,它会使用当前的调度器——如果假设它能够使用当前线程,那么在等待它的时候,你将会有效地死锁。

相同的代码在不同的上下文中就可以了。

别人说它适合他们,但不适合你的原因是,毫无疑问,你是在不同的上下文中运行这段代码的——但你没有给我们展示一个简短但完整的程序,只是这个片段,所以每个人都试图以不同的方式复制它。(我看到你现在已经上传了一个项目,毫无疑问,这将带来更多的启示。当然,一个简短但完整的程序可以张贴在问题中通常是更好的。

感谢大家的意见,它帮助我更具体,并最终隔离问题。

我创建了一个测试项目:http://erwinmayer.com/dl/TaskTestProject.zip。它表明,如果在静态构造函数中运行,我的问题中的代码将不起作用。但是,如果在初始化静态构造函数之后,将其作为静态类方法直接调用,则可以工作。

这篇最近的MSDN博客文章提供了一些在处理多线程和静态构造函数时存在的相关问题的技术见解:

效果:

        var task = new Task(() => { });
        task.Start();
        if (task.Wait(10000))
        {
            Console.WriteLine("yes");
        }
        else
        {
            Console.WriteLine("no");
        }

给出了预期的输出yes。你一定是在做其他事情导致它不起作用。在给定的形式下,没有上下文说明你在做什么/在哪里,它是有效的。

即使这个讨厌的工作:

        var task = new Task(() =>
                                {
                                    var task1 = new Task(() =>
                                                            {
                                                            });
                                    task1.Start();
                                    if (task1.Wait(10000))
                                    {
                                        Console.WriteLine("yes");
                                    }
                                    else
                                    {
                                        Console.WriteLine("no");
                                    }
                                });
        task.Start();
        if (task.Wait(10000))
        {
            Console.WriteLine("yes");
        }
        else
        {
            Console.WriteLine("no");
        }