线程和任务调度

本文关键字:任务调度 线程 | 更新日期: 2023-09-27 18:28:40

我有一个通过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.Run相同的顺序调用它们?

线程和任务调度

  1. 不,这并不能保证,你只是很幸运,每次的输出都是一样的
  2. 在两个任务之间添加具有WaitOne的第二个AutoResetEvent,并在Waiter方法开始时添加Set

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

因此,为了回答您的问题:

在前进之前,你应该问问自己"我真的需要使用线程来解决这个问题吗?"

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

"当你使用任何类型的多线程时,你都可能会暴露出非常严重和复杂的错误"[

如果您确实需要介绍线程,那么我将首先熟悉微软的一些同步机制:

  • 关键部分
  • Mutex
  • 事件
    • 自动复位
    • 手动复位