Чтобы сделать выбор между ManualResetEvent или Thread.Sleep()

Я не уверен, какую стратегию принять... Я сосредотачиваюсь на завершении моей работы, но я также хотел бы сохранить проблемы с производительностью до минус... есть метод под названием Выполнять ( ), который должен ждать (запускать синхронно) до завершения операции. Эта операция выполняется в другом потоке. Есть два способа реализовать одно и то же...

Используя ManualResetEvent

void Execute()
{
    taskHandle = new ManualResetEvent(false);
    .
    .
    //delegate task to another thread
    .
    .
    taskHandle.WaitOne();
}

ИЛИ

Используя простую конструкцию

void Execute()
{
    .
    .
    //delegate task to another thread
    .
    .
    while (!JobCompleted)
        Thread.Sleep(1000);
}

Какой из двух подходов я должен принять... почему?

EDIT:

Q2. Что, если у меня просто было пустое место? В чем разница...?

while(!JobCompleted);

EDIT: (что-то, что я собрал раньше)

http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - В этой статье говорится, что manualresets являются сравнительно медленными, потому что они выходят из управляемого кода и обратно...

Ответ 1

Из любопытства, почему ManualResetEvent а не AutoResetEvent? В любом случае, подойдите к примитиву ОС под спящим режимом сна.

Вы также можете использовать блокировку Monitor (либо явно через Monitor.Enter и Monitor.Exit, либо через блок lock), но этот подход должен основываться на том, что вы на самом деле делаете; если это сценарий "есть только одна из этих вещей, и мне нужен эксклюзивный доступ", используйте блокировку Monitor. Если это "мне нужно подождать, пока другой поток не закончится по причинам, отличным от доступа к ресурсам", используйте AutoResetEvent или ManualResetEvent.

Предложения по использованию Thread.Join хороши, если (и только если)

  • У вас есть доступ к другому объекту Thread
  • Вы не хотите выполнять выполнение, пока другой поток не завершится.

Если это неверно (у вас нет доступа или другой поток не будет завершен, он будет просто сигнализировать "все ясно" ), тогда Thread.Join не является жизнеспособным.

Самый худший вариант -

while(!JobCompleted);

Так как это свяжет процессор с ненужными проверками переменной без какой-либо паузы между ними. Да, он заблокирует ваш поток до тех пор, пока операция не завершится, но вы не сможете использовать CPU (или, по крайней мере, одно ядро).

Ответ 2

Событие более эффективно использует процессоры - вам не нужно разбудить родительский поток до опроса. Ядро разбудит вас при срабатывании события.

Ответ 3

Если у вас есть доступ к исходному объекту Thread или вы можете получить этот доступ, вам лучше использовать Thread.Join().

Edit: Кроме того, если это происходит в графическом интерфейсе, таком как WinForms или WPF, вам может потребоваться использовать BackgroundWorker

Ответ 4

Основным недостатком использования Thread.Sleep() является то, что вы принимаете решение о том, как долго будет ждать поток. Операция, которую вы ожидаете, может занять больше или меньше, и в целом очень сложно точно определить это время. Если поток слишком длинный, вы не используете системные ресурсы наилучшим образом.

Чтобы быть оптимальным, вы должны использовать ManualResetEvent (или AutoResetEvent), чтобы поток возобновлялся, как только завершилась зависимая операция.

Ответ 5

ManualResetEvent - это, безусловно, путь.

Из приведенного фрагмента кода похоже, что вы делегируете выполнение в своем методе Execute. Если это так, и вы делегируете только одну задачу, почему вы делегируете другой поток вообще, если вам нужно ждать ответа? Вы можете просто выполнить процесс синхронно.

Ответ 6

manualresets сравнительно медленнее, потому что они выходят из управляемого кода и обратно.

Они, вероятно, медленнее, чем говорят Wait/Pulse combo, которые вы должны использовать здесь, на мой взгляд,. Но Manual/AutoResetEvents будет быстрее, чем любой Thread.Sleep(x), который вы делаете, даже если вы выберете x = 1. И даже если вы понизите разрешение таймера Windows до 1 мс.

Что делать, если у меня только что был пустой? В чем разница...?

Затем одно ядро ​​будет вращаться на 100% до тех пор, пока условие не станет истинным, уберет время от других потоков, которые могли бы вместо этого использовать его, чтобы сделать что-то полезное, например, вычислять кадры для "Angry Birds" - или процессор может просто охладить бит, задерживая ужасные последствия глобального потепления для некоторых последующих наносекунд.

Ответ 7

Оба подхода делают одно и то же в основном. Однако цикл while немного более явный, поскольку вы можете указать время сна. Хотя я бы использовал классы XXXResetEvent, которые предназначены для использования в сценарии, в котором вы работаете. Я бы предположил, что классы потоковой передачи будут реализованы сейчас или позже с более надежным кодом потока, чтобы обрабатывать, возможно, привязанность потоков к многоядерным процессорам.