2013-10-24 2 views
18

В этой статье: http://msdn.microsoft.com/en-us/magazine/cc164015.aspx автор утверждает, что System.Threading.Timer не является потокобезопасным.Thread-safety System.Timers.Timer vs System.Threading.Timer

С тех пор это повторялось в блогах, в книге Рихтера «CLR через C#», на SO, но это никогда не оправдано.

Кроме того, MSDN documentation обеспечивает «этот тип потокобезопасен».

1) Кто говорит правду?

2) Если это оригинал статьи, что делает System.Threading.Timer не поточно-и как его обертка System.Timers.Timer достигает более потокобезопасности?

Thanks

+0

Защита резьбы для каких операций? Вы хотите изменить таймер одновременно? – usr

+3

Нить-безопасность может означать много вещей, поэтому все правы. –

+0

@usr: ну, может быть, я слишком простой, но для меня тип называется потокобезопасным, если любой экземпляр можно использовать из потоков 654139846535821 одновременно, не повреждая его состояние. Если у вас есть другое определение, делитесь им. Спасибо :) – Pragmateek

ответ

35

Нет, это не так, как работает. Асинхронные классы таймера .NET отлично потокобезопасны. Проблема с безопасностью потоков заключается в том, что она не является транзитивным свойством, она не делает код другим кодом, который также выполнен поточно-безопасным. Код, который вы написали, а не программист .NET Framework.

Это такая же проблема с распространенным предположением, что код пользовательского интерфейса Windows в основном небезопасен. Это не так, код внутри Windows отлично потокобезопасен. Проблема заключается в том, что весь код, который работает, является не частью Windows и не написан программистом Microsoft. Всегда есть лот этого кода, вызванный вызовом SendMessage(). Какая программа выполняет собственный код, который написал программист. Или код, который он не писал, как крючок, установленный какой-то утилитой. Код, предполагающий, что программа не затрудняет работу и просто выполняет обработчики сообщений в одном потоке. Обычно он делает, не делая этого, покупает ему лот проблемы.

Такая же проблема с событием System.Timers.Timer.Elapsed и обратным вызовом System.Threading.Timer. Программисты делают лотов ошибок, записывающих этот код. Он работает асинхронно в произвольном потоке threadpool, прикосновение к любой общей переменной действительно требует блокировки для защиты состояния. Очень легко упускать из виду. И что еще хуже, намного хуже, очень легко попасть в груду проблем, когда код снова запустил , прежде чем предыдущий вызов прекратил работу. Запускается, когда интервал таймера слишком низкий или слишком загружена машина. Теперь есть два потока, работающих по тому же коду, что редко приходит к хорошему концу.

Резьба трудно, новости в одиннадцать.

+2

Спасибо Хансу за то, что он напомнил нам об этом фундаментальном принципе. Я знаю об этом вопросе (узнал это нелегко;)). Но некоторые люди (а не только любой) заявляют, что фундаментальное различие между этими таймерами - это безопасность потоков. Как обсуждалось с Henk, и, как вы говорите, оба они должны считаться потокобезопасными или оба должны считаться небезопасными. Может быть, объяснение простое: исходный источник был неправильным (например, потому что на основе ранней альфа-реализации), а остальные просто повторяли это неправильное утверждение. Но я хотел бы быть уверен. – Pragmateek

+1

Это отличный ответ. @Pragmateek, вы должны принять это как ответ IMHO – dotnetguy

+4

@mishrsud: причина, по которой этот ответ не был принят, - это не его качество, которое действительно превосходно, но разумное сомнение, которое все еще существует, потому что у других источников были противоположные взгляды на эту тему. Но давайте рассмотрим Ганса как окончательный источник (ИМХО - разумная гипотеза), поэтому я соглашусь с ним. :) – Pragmateek

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