Я бы сказал, что написание многопоточных приложений - одна из самых сложных вещей для понимания и правильного выполнения. Вы действительно должны прочитать об этом. Если вы узнали C # из книги, вернитесь и посмотрите, нет ли главы о многопоточности. Я узнал из книг Эндрю Троелсена (последняя была Pro C # 2005 и платформа .NET 2.0 ), он не затрагивает эту тему до главы 14 (поэтому к тому времени многие перестали читать). Я пришел из опыта встраиваемого программирования, где параллелизм и атомарность также являются проблемой, так что это не проблема .NET или Windows.
Многие из этих постов подробно описывают механизм работы с потоками с помощью средств, поставляемых в .NET. Все ценные советы и вещи, которые вы должны выучить, но это действительно поможет, если вы сначала лучше познакомитесь с «теорией». Возьмите проблему с многопоточностью. Что действительно происходит, так это то, что поток пользовательского интерфейса имеет некоторую встроенную сложность, которая проверяет, изменяете ли вы элемент управления из другого потока. Дизайнеры MS поняли, что сделать ошибку было легко, поэтому была встроенная защита от нее. Почему это опасно? Это требует, чтобы вы поняли, что такое атомарная операция. Так как «состояние» элемента управления не может быть изменено в элементарной операции, один поток может начать изменять элемент управления, а затем другой поток может стать активным, оставляя элемент управления в частично измененном состоянии. Теперь, если вы скажете пользовательскому интерфейсу, что я не даю дерьма, просто позвольте моему потоку изменить элемент управления, он может работать. Однако, когда это не сработает, вам будет очень сложно найти ошибку. Вы сделаете свой код намного менее обслуживаемым, и программисты, которые последуют за вами, будут проклинать ваше имя.
Итак, пользовательский интерфейс сложен и проверяет вас, а классы и потоки, которые вы пишете, - нет. Вы должны понимать, что является атомным в ваших классах и потоках. Вы можете быть причиной "заморозки" в ваших темах. Чаще всего зависание приложения является результатом тупиковой ситуации. В этом случае «заморозить» означает, что пользовательский интерфейс никогда не станет реагировать снова. В любом случае это становится слишком длинным, но я думаю, что как минимум вы должны быть знакомы с использованием «блокировки», а также, вероятно, Monitor, interlocked, семафоров и мьютексов.
Просто чтобы дать вам идею: (из книги Троелсена)
intVal++; //This is not thread safe
int newVal = Interlocked.Increment(ref intVal); //This is thread safe
.NET также предоставляет атрибут [Синхронизация]. Это может облегчить написание потокового класса, но вы платите за эффективность его использования. Что ж, я просто надеюсь дать вам некоторое представление о сложностях и побудить вас пойти дальше читать.