2016-01-02 4 views
3

У меня есть код, который синхронизация потоков с помощью AutoResetEventрезьбы и планирование Задачи

В основном есть два потока, которые SWAP управления и выполнение команд, каждый поток одновременно.

Код:

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()); 

я иногдаget:

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 s для вызова того же порядка, что и я их вызываю?

+0

Порядок исполнения не гарантируется. Кроме того, это очень плохая идея, чтобы несколько потоков ожидали того же 'AutoResetEvent', подумайте об этом ... [This] (http://blog.mikejmcguire.com/2014/12/22/using-the-autoresetevent -class-to-wake-multiple-threads-in-c /) является хорошим чтением. –

+0

@WouterHuysentruit Спасибо. –

ответ

3
  1. Нет, это не гарантировано, вам просто повезло, что выход был тот же каждый раз.
  2. Добавить в 2 AutoResetEvent, который имеет WaitOne между двумя задачами и Set в начале метода Waiter.
+0

Скотт, скажем, у меня есть 10 тем, а не 2, и я хочу то же самое - у меня должно быть 20 waithandles? –

+0

Нет, вам просто нужно WaitOne между каждым методом и Set в начале каждого метода, используя тот же AutoResetEvent, что и первый WaitOne –

3

Без механизма синхронизации вы не можете гарантировать порядок запуска и/или выполнения потока. Кроме того, выполнение потока может быть выгружено (думаю: «приостановлено») в любое время.

Так, чтобы ответить на ваши вопросы:

  1. Нет
  2. Нет

Прежде чем двигаться вперед, вы должны спросить себя: «Действительно ли я должен использовать нити, чтобы решить эту проблему?"

Моя любимая цитата из MSDN в компании Microsoft:

„При использовании многопоточности любого рода, вы потенциально подвергать себя очень серьезные и сложные ошибки“[Best Practices for Implementing the Event-based Asynchronous Pattern]

Если вам не нужно для введения потоков, я бы начал с ознакомления с некоторыми механизмами синхронизации Microsoft:

+0

Как здесь относится критический раздел. ? Кроме того, я не вижу, как ваша сторонняя часть способствует вашему ответу. Дело не в том, что я не знаком с предметом. У меня был вопрос о расписании. Thats all :-) –

+0

Ваш исходный вопрос относится к механизмам синхронизации потоков. Одним из таких примеров является критический раздел. – Pressacco

+0

Я не согласен. Блокировка обеспечивает один поток в разделяемом разделе кода. У меня не было этой проблемы. Но в любом случае .... –

Смежные вопросы