【发布时间】:2018-04-28 07:00:06
【问题描述】:
我始终通过线程池运行三个操作。它们具有相同的优先级。但是,它们的执行顺序并不总是我运行它们的顺序。为什么会这样?
我预计线程池将按照我将它们发布到线程池的查询队列中的顺序启动我的任务(如果它们具有相同的优先级)。
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();
}
}
}
【问题讨论】:
-
三个线程没有达到按您将它们排队的顺序产生输出的点这一事实并不意味着它们没有按照您将它们排队的顺序启动。请记住它实际上是机器代码被执行,而不是 C# 代码,所以你的一行代码实际上会导致机器执行许多指令。
-
@jmcilhinney 如果我将许多将一些信息写入流(而不是控制台输出)的小任务放入线程池 qwery 队列中会怎样?在这种情况下,书写顺序对我来说非常重要,否则文档格式会出错。
-
操作系统不提供任何保证来公平地分配线程之间的处理器时间。即使
ThreadPool将保证工作项将按照它们排队的顺序开始(它不会),你仍然不能保证它们以与开始时相同的顺序完成工作。 -
如果您需要有序并行处理,则不能使用 QueueUserWorkItem。您应该查看 PLINQ 扩展方法,它是
Ordered()扩展来完成您的并行工作。 -
另外,为什么顺序很重要?
标签: c# .net multithreading threadpool