C# System.Threading.Tasks不遵守启动规则?

C# System.Threading.Tasks不遵守启动规则?,c#,.net,multithreading,task,C#,.net,Multithreading,Task,重写:我已经将问题剥离,以包含示例代码,而不是指向它的链接以及结果和问题,因为周围的信息似乎正在引起混乱 问题:为什么任务似乎一开始就没有启动 这是来自on tasks的一段示例代码。它被描述为创建一个未启动的任务,创建第二个启动的任务并等待它完成,然后启动第一个任务,最后在主线程中同步启动第三个任务 以下是示例代码的未注释版本: using System; using System.Threading; using System.Threading.Tasks; class StartNew

重写:我已经将问题剥离,以包含示例代码,而不是指向它的链接以及结果和问题,因为周围的信息似乎正在引起混乱

问题:为什么任务似乎一开始就没有启动

这是来自on tasks的一段示例代码。它被描述为创建一个未启动的任务,创建第二个启动的任务并等待它完成,然后启动第一个任务,最后在主线程中同步启动第三个任务

以下是示例代码的未注释版本:

using System;
using System.Threading;
using System.Threading.Tasks;

class StartNewDemo
{
    static void Main()
    {
        Action<object> action = (object obj) =>
        {
            Console.WriteLine("Task={0}, obj={1}, Thread={2}", Task.CurrentId, obj.ToString(), Thread.CurrentThread.ManagedThreadId);
        };

        Task t1 = new Task(action, "alpha");

        Task t2 = Task.Factory.StartNew(action, "beta");

        t2.Wait();

        t1.Start();

        Console.WriteLine("t1 has been launched. (Main Thread={0})", Thread.CurrentThread.ManagedThreadId);

        t1.Wait();

        Task t3 = new Task(action, "gamma");

        t3.RunSynchronously();

        t3.Wait();
    }
}
从描述中可以看出,任务1是测试版,应该仅在任务2完成后运行,这样主线程才能继续。从这个输出来看,情况似乎并非如此。我还运行了第二次测试运行,其中我将滴答数的显示放入action对象中,并收到了此消息,确认Task1确实在Task2完成之前启动

Task=1, obj=beta, Thread=3 (634529151744201906)
t1 has been launched. (Main Thread=1)
Task=2, obj=alpha, Thread=3 (634529151744221908)
Task=3, obj=gamma, Thread=1 (634529151744221908)

我不想在这里做任何花哨的事情,我只是想解释一下为什么Task1(obj=beta)显然是在得到执行指令之前执行的。

如果没有某种形式的同步,线程或
任务的分配
不能保证(即非确定性)是有序的

如果没有某种形式的同步,则不能保证线程或将
任务
分配给线程(即非确定性)处于有序状态

Task=1, obj=beta, Thread=3
Task=1在这里有点误导,因为这实际上是示例代码中的t2。您可以看到这一点,因为存在“beta”。它在运行t1之前启动并完成

t1 has been launched. (Main Thread=1)
Task=2, obj=alpha, Thread=3
这是t1(Id为2)

这里是t3

Task=1在这里有点误导,因为这实际上是示例代码中的t2。您可以看到这一点,因为存在“beta”。它在运行t1之前启动并完成

t1 has been launched. (Main Thread=1)
Task=2, obj=alpha, Thread=3
这是t1(Id为2)


这是t3。

启动任务时,它可能不会立即执行(如果没有可用线程池线程)。但任务永远不会自己开始。你观察到的结果是正确的

代码的执行方式如下:

  • t1
    alpha
    )已创建,但未执行
  • t2
    beta
    )被创建、启动、打印到控制台(显然是使用
    TaskId==1
    )并等待
  • t1
    alpha
    )启动,显然是使用
    TaskId==2
  • 打印关于启动
    t1
    的通知
  • t1
    alpha
    )打印到控制台并等待
  • 剩下的应该是显而易见的

启动任务时,它可能不会立即执行(如果没有可用线程池线程)。但任务永远不会自己开始。你观察到的结果是正确的

代码的执行方式如下:

  • t1
    alpha
    )已创建,但未执行
  • t2
    beta
    )被创建、启动、打印到控制台(显然是使用
    TaskId==1
    )并等待
  • t1
    alpha
    )启动,显然是使用
    TaskId==2
  • 打印关于启动
    t1
    的通知
  • t1
    alpha
    )打印到控制台并等待
  • 剩下的应该是显而易见的


“我正在使用的软件需要仔细控制在工作流程的特定阶段点亮多少或哪些内核”-您能解释一下原因吗?如果代码适用于多线程,为什么它需要一个特定的核心计数?从问题中删除该行,因为它与问题无关。我想我提供了太多的背景信息。“我正在使用的软件需要仔细控制在工作流程的特定阶段有多少或哪些内核点亮”-你能解释一下原因吗?如果代码适用于多线程,为什么它需要一个特定的核心计数?从问题中删除该行,因为它与问题无关。我想是提供了太多的背景信息。所以一个任务可以在没有调用.start()或由工厂的.StartNew()创建的情况下启动?啊,这是我的问题,为什么任务似乎不服从开始,直到被告知这样做。你一行一行地调试了这个问题吗?我重新编写了这个问题,更准确地说,我已经做了一些调试,试图弄清楚这一点,但丹已经表明了我所误解的。无论如何,谢谢你。这样一个任务就可以不用调用.start(),或者由工厂的.StartNew()创建就可以开始了?啊,这是我的问题,为什么任务似乎不服从开始,直到被告知这样做。你一行一行地调试了这个问题吗?我重新编写了这个问题,更准确地说,我已经做了一些调试,试图弄清楚这一点,但丹已经表明了我所误解的。无论如何谢谢你。我是个傻瓜,没有注意到这一点,谢谢。我误读了结果!多谢各位@James,一个有趣的结果是任务Id显然是在计划任务时设置的,而不是在构建任务时设置的。很好,如果可以的话,我会给你+2,因为这样可以避免我依赖Id。我是个傻瓜,没有注意到这一点,谢谢。我误读了结果!多谢各位@James,一个有趣的结果是任务Id显然是在计划任务时设置的,而不是在构建任务时设置的。很好的一点,如果可以的话,我会给你+2,因为这样可以避免我依赖Id。对于一个好的答案+1,以及一个更早的答案。虽然我先读了丹的答案并将其标记为答案,但由于答案的顺序很奇怪。@James,相同分数的答案是随机排列的。我认为你可以改变你的想法,什么是公认的答案。好答案+1,以及更早的答案。虽然我的回答顺序很奇怪
Task=3, obj=gamma, Thread=1