2010-08-05 1 views
3

Каков наиболее эффективный способ создания события «отменить» в программе на C#, которая хрустает большой набор данных в цикле в отдельном потоке?Эффективное отмена реализации событий для потоков с чередованием чисел?

В настоящее время я просто использую событие отмены, которое запускается из моего потока пользовательского интерфейса, который впоследствии вызывает функцию onCancel на число хрустящей нити. Эта функция отмены устанавливает переменную в значение «true», которую периодически проверяет цикл хруста, например.

Class Cruncher { 
    private bool cancel = false; 

    public cruncher() 
    { 
     crunch(); 
    } 

    private void crunch() 
    { 
     while(conditions AND !cancel) { crunch; } 

     dispose_resources; 
    } 

    private void onCancel() 
    { 
     cancel = true; 
    } 
} 

Пока я не проверяя отменить переменную так часто, как мой пример выше (и на самом деле не выполняя НЕ отменить), я все же хотел бы оптимизировать этот метод хруст как можно больше. Любые примеры, где это делается более эффективно, было бы очень приятно увидеть.

+1

В очень плотных циклах я оптимизировал, проверяя только каждые 100 или 1000 итераций вместо каждого. Но вам нужно проверить. –

ответ

3

Отмена события/флаг должен быть volatile ... Я спросил, очень похожий вопрос твой: Is it safe to use a boolean flag to stop a thread from running in C#

Я хотел бы также рекомендовать, что, когда вы отмените темы вы ждете для всех из них, чтобы отменить с помощью что-то похожее на C# version of CountDownLatch. Это полезно, когда вы хотите гарантировать, что поток отменен.

+0

У вас был вопрос, который я пытался найти в моих поисках! – rnd

+0

@ rnd, рад, что я мог бы помочь! – Kiril

1

В конечном итоге это всегда приводит к чему-то подобному - хотя важно, чтобы вы изменяли переменную cancel, так как в противном случае рабочие потоки могут не видеть изменения от отменой потока.

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

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

+0

C# в глубине в настоящее время находится на грузовике, направляющемся к Амазонке. С нетерпением жду этого! – rnd

0

Я сделал бы это таким же образом. я также добавлю Thread.Sleep в цикл, чтобы получить контроль над основным потоком.

http://msdn.microsoft.com/en-us/library/7a2f3ay4%28VS.80%29.aspx

+0

Я не думаю, что Thread.Sleep необходим, когда реализована правильная сигнализация (т. Е. Monitor или CountDownLatch). – Kiril

+0

согласен, я говорил о простой проверке переменных внутри цикла. – akonsu

1

Тем более, что это UI срабатывает, я бы рекомендовал только усиливая BackgroundWorker, который уже в рамках, тем более, что это будет приятно иметь прогресс и сделали события происходят в потоке пользовательского интерфейса для вас (так вам не нужно ссылаться на себя).

Тогда вы можете просто использовать вызов CancelAsync(). По общему признанию, это не сильно отличается от того, что вы уже делаете, только что сделано в рамках уже (и в том числе логики синхронизации потоков)

Как сказал Джон, вы все равно захотите сделать совместное аннулирование (проверка CancellationPending в DoWork для использования BackgroundWorker), поскольку опция «прерывать/прервать поток» - это то, чего вы хотите избежать, если это возможно.

Если в .NET 4 вы можете использовать TPL и new Cancellation support, но опять же он ориентирован на совместное аннулирование.

+0

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

1

Я рекомендую использовать unified cancellation model, который был представлен в .NET 4.0 (если .NET 4.0 является опцией).

Он очень эффективен и позволяет интегрировать отмену с объектами Task и Parallel LINQ.

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