Я должен заблокировать или отметить как энергозависимого при доступе к простому булеву флагу в C#?

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

43
задан Simon P Stevens 3 August 2009 в 13:02
поделиться

5 ответов

Во-первых, многопоточность - дело сложное ;-p

Да, несмотря на все слухи об обратном, требуется для либо использования lock или volatile (но не оба сразу) при доступе к bool из нескольких потоков.

Для простых типов и доступа, таких как флаг выхода ( bool ), тогда volatile будет достаточно - это гарантирует, что потоки не кэшируют значение в своих регистрах (что означает: один из потоков никогда не видит обновления).

Для больших значений (где атомарность является проблемой), или если вы хотите синхронизировать последовательность операций (типичный пример - «если не существует, добавьте» доступ к словарю), блокировка более универсальна. Это действует как барьер памяти, так что по-прежнему обеспечивает безопасность потоков, но предоставляет другие функции, такие как импульс / ожидание. Обратите внимание, что вы не должны использовать блокировку для типа значения или строки ; ни Тип или это ; лучший вариант - иметь собственный блокирующий объект в качестве поля ( readonly object syncLock = new object (); ) и заблокировать его.

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

Чтобы охватить несколько программ, примитив ОС, такой как Mutex или * ResetEvent , также может быть полезен , но это перебор для одного exe.

ни Тип или это ; лучший вариант - иметь собственный блокирующий объект в качестве поля ( readonly object syncLock = new object (); ) и заблокировать его.

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

Чтобы охватить несколько программ, примитив ОС, такой как Mutex или * ResetEvent , также может быть полезен , но это перебор для одного exe.

ни Тип или это ; лучший вариант - иметь собственный блокирующий объект в качестве поля ( readonly object syncLock = new object (); ) и заблокировать его.

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

Чтобы охватить несколько программ, примитив ОС, такой как Mutex или * ResetEvent , также может быть полезен , но это перебор для одного exe.

39
ответ дан 26 November 2019 в 23:05
поделиться

Блокировка не требуется, потому что у вас есть сценарий с одним записывающим устройством, а логическое поле представляет собой простую структуру без риска повреждения состояния (, хотя можно было получить логическое значение, которое не является ни ложным, ни истинным ). Но вы должны пометить поле как volatile , чтобы компилятор не выполнял некоторые оптимизации. Без модификатора volatile компилятор мог бы кэшировать значение в регистре во время выполнения вашего цикла в рабочем потоке, и, в свою очередь, цикл никогда не распознал бы измененное значение. Эта статья MSDN ( Как: Хотя существует необходимость в блокировке, блокировка будет иметь тот же эффект, что и пометка поля изменчивым .

5
ответ дан 26 November 2019 в 23:05
поделиться

Найдите Interlocked.Exchange () . Он очень быстро копирует в локальную переменную, которую можно использовать для сравнения. Это быстрее, чем lock ().

1
ответ дан 26 November 2019 в 23:05
поделиться

_cancelled must be volatile. (if you don't choose to lock)

If one thread changes the value of _cancelled, other threads might not see the updated result.

Also, I think the read/write operations of _cancelled are atomic:

Section 12.6.6 of the CLI spec states: "Соответствующий интерфейс командной строки должен гарантировать, что доступ для чтения и записи к правильному выровненные ячейки памяти не больше чем исходный размер слова атомарен когда все записи обращаются к location are the same size."

6
ответ дан 26 November 2019 в 23:05
поделиться

For thread synchronization, it's recommended that you use one of the EventWaitHandle classes, such as ManualResetEvent. While it's marginally simpler to employ a simple boolean flag as you do here (and yes, you'd want to mark it as volatile), IMO it's better to get into the practice of using the threading tools. For your purposes, you'd do something like this...

private System.Threading.ManualResetEvent threadStop;

void StartThread()
{
    // do your setup

    // instantiate it unset
    threadStop = new System.Threading.ManualResetEvent(false); 

    // start the thread
}

In your thread..

while(!threadStop.WaitOne(0) && !operationComplete)
{
    // work
}

Then in the GUI to cancel...

threadStop.Set();
2
ответ дан 26 November 2019 в 23:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: