为什么线程池可以以相同的优先级启动我的任务,而不是以我发布它们的相同顺序?

Why the thread pool can launch my tasks with the same priority not in the same order I posted them?

我一直运行通过线程池进行3次操作。它们具有相同的优先级。但是,它们的执行顺序并不总是我 运行 它们的顺序。为什么会这样?

我预计线程池将按照我将它们发布到线程池的查询队列中的相同顺序启动我的任务(如果它们具有相同的优先级)。

using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;

namespace ThreadsLearning {

    class Foo {
        public string Name { get; set; }

        public override string ToString() {
            return Name;
        }
    }

    class Program {

        private static void Main(string[] args) {

            Console.WriteLine("Main method works...");

            Foo foo = new Foo { Name = "Bob" };

            CallContext.LogicalSetData("name", foo);

            ThreadPool.QueueUserWorkItem(state => Console.WriteLine("1: Name = {0}",
            CallContext.LogicalGetData("name")));

            ExecutionContext.SuppressFlow();

            ThreadPool.QueueUserWorkItem(state => Console.WriteLine("2: Name = {0}",
                CallContext.LogicalGetData("name")));

            ExecutionContext.RestoreFlow();

            ThreadPool.QueueUserWorkItem(state => Console.WriteLine("3: Name = {0}",
                CallContext.LogicalGetData("name")));

            Console.WriteLine("Hit <Enter> for exit...");
            Console.ReadLine();
        }
    }
}

输出可以是:

Main method works...
Hit <Enter> for exit...
2: Name =
1: Name = Bob
3: Name = Bob

Main method works...
1: Name = Bob
2: Name =
3: Name = Bob
Hit <Enter> for exit...

UPD

我尝试对流进行同样的操作,但遇到了同样的问题:

using System;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;

namespace ThreadsLearning {

    class Foo {
        public string Name { get; set; }

        public override string ToString() {
            return Name;
        }
    }

    class Program {

        private static void Main(string[] args) {

            using (MemoryStream ms = new MemoryStream()) {

                using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8, 0x1000, true)) {
                    sw.WriteLine("Main method works...");

                    Foo foo = new Foo { Name = "Bob" };

                    CallContext.LogicalSetData("name", foo);

                    ThreadPool.QueueUserWorkItem(state => sw.WriteLine("1: Name = {0}",
                        CallContext.LogicalGetData("name")));

                    ExecutionContext.SuppressFlow();

                    ThreadPool.QueueUserWorkItem(state => sw.WriteLine("2: Name = {0}",
                        CallContext.LogicalGetData("name")));

                    ExecutionContext.RestoreFlow();

                    ThreadPool.QueueUserWorkItem(state => sw.WriteLine("3: Name = {0}",
                        CallContext.LogicalGetData("name")));

                    Thread.Sleep(2000); // Postpone the ws.Dispose() call.
                }

                using (StreamReader sr = new StreamReader(ms, Encoding.UTF8)) {
                    Console.WriteLine("Stream length: {0} bytes", ms.Length);
                    ms.Position = 0;
                    Console.WriteLine("Data: \n{0}", sr.ReadToEnd());
                }
            }

            Console.WriteLine("Hit <Enter> for exit...");
            Console.ReadLine();
        }
    }
}

Threadpool 使用一个 Queue 输入 "things to do" 并从中取出 "things to do"。

添加任务时,它会将其放置在可用槽位中,只需查看 Visual Studio 中的 window,您就会发现它不是队列,而是一个队列固定大小的数组(如果变大可以增长)参见 "JustDecompile"

中的图像

如果您的逻辑要求您先执行第 1 步,然后再执行第 2 步,则您不能使用该方法,"multi threading" 的本质是您在某种程度上孤立的后台启动某些内容,"statement of work",按设计工作,一旦资源可用就运行任务。

在查看该行为时,会给您带来预期流量的是 Task.ContinueWith(action), you can chain actions together as shown here