【问题标题】:Thread and Task scheduling线程和任务调度
【发布时间】:2016-01-02 18:28:45
【问题描述】:

我有一个通过AutoResetEvent同步线程的代码

基本上有两个线程交换控制和执行命令,每个线程一次。

代码

static EventWaitHandle _waitHandle = new AutoResetEvent(false);
static void Waiter()
{

    _waitHandle.WaitOne();
    Console.WriteLine("A...");
    _waitHandle.Set();  
    _waitHandle.WaitOne();
    Console.WriteLine("A2...");
    _waitHandle.Set();
}

static void Waiter2()
{   
    _waitHandle.WaitOne();
    Console.WriteLine("B...");
    _waitHandle.Set();
    _waitHandle.WaitOne();
    Console.WriteLine("B2...");
}


void Main()
{
    new Thread(Waiter).Start();
    new Thread(Waiter2).Start();
   _waitHandle.Set(); // Wake up the Waiter.
}

结果:(我总是得到这个结果)

A...
B...
A2...
B2...

但是 - 当我搬到 Tasks 时:

Task.Run(()=>Waiter());
Task.Run(()=>Waiter2());

我有时会得到:

B...
A...
B2...

这对我来说很清楚,因为任务调度程序安排了第二个任务首先执行。

这让我问:

问题

1) 线程顺序是否保证与调用顺序相同:

new Thread(Waiter).Start();
new Thread(Waiter2).Start();
//In other words , will I always get the first result ?

2) 如何强制Task.Runs 以与我调用它们相同的顺序被调用?

【问题讨论】:

  • 不保证执行顺序。此外,让多个线程等待同一个AutoResetEvent 是一个非常糟糕的主意,请考虑一下……This 是一本好书。
  • @WouterHuysentruit 谢谢。

标签: c# multithreading


【解决方案1】:
  1. 不,不能保证,您很幸运每次输出都相同。
  2. 添加第二个AutoResetEvent,在两个任务之间有一个WaitOne,并在Waiter方法的开头添加一个Set

【讨论】:

  • Scott,说我有 10 个线程,而不是 2 个,我想要同样的东西 - 我必须有 20 个等待句柄吗?
  • 不,您只需要在每个方法之间有一个 WaitOne,并在每个方法的开头使用一个与第一个 WaitOne 相同的 AutoResetEvent 的 Set
【解决方案2】:

如果没有同步机制,您无法保证线程启动和/或执行的顺序。此外,线程的执行可能随时被抢占(想想:“暂停”)。

所以回答你的问题:

  1. 没有
  2. 没有

在继续前进之前,您应该问自己“我真的需要使用线程来解决这个问题吗?”

我最喜欢微软 MSDN 中的一句话:

“当您使用任何类型的多线程时,您可能会遇到非常严重和复杂的错误”[Best Practices for Implementing the Event-based Asynchronous Pattern]

如果您确实需要引入线程,那么我将首先让您熟悉一些 Microsoft 的同步机制:

【讨论】:

  • 这里的关键部分是如何关联的。 ?此外,我看不出您的旁白部分对您的回答有何贡献。并不是我不熟悉这个主题。我有一个日程安排问题。就是这样:-)
  • 您最初的问题与线程同步机制有关。关键部分就是这样一个例子。
  • 我不同意。 Lock 确保一个线程在共享代码部分。我没有那个问题。但无论如何....
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 2021-02-09
  • 1970-01-01
  • 2013-02-03
相关资源
最近更新 更多