Гарантирует ли BackgroundWorker, что изменения памяти, сделанные в фоновом потоке, становятся видимыми для основного потока?

Если я использую BackgroundWorker для изменения структур данных в моем приложении, есть ли гарантия, что изменения, внесенные в фоновый поток, будут видны основному (UI) потоку после завершения BackgroundWorker (например, в обработчике событий RunWorkerCompleted)? Для бонусных баллов: если так, какой механизм это гарантирует?

2 ответа

Решение

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

Конечно, если вы используете встроенные механизмы BGW для передачи данных между потоками, например, через Result или же Progress данные, которые он хранит, то он будет правильно синхронизировать доступ к этим данным.

Да, вам не о чем беспокоиться, если вы следуете контракту с BackgroundWorker. Другими словами, используйте предоставленные события для направления данных в поток пользовательского интерфейса, ProgressChanged и RunWorkerCompleted. Исходный код.NET Framework за это не получает баллов за элегантность, синхронизация не является явной. Это довольно распространенное явление, оно опирается на неявную синхронизацию во многих местах.

Но есть два, которые гарантируют, что поток пользовательского интерфейса может видеть обновления. Во-первых, это PostMessage(), функция winapi, которая используется для оповещения потока пользовательского интерфейса о том, что ему нужно взглянуть на очередь вызовов. При использовании здесь вы, тем не менее, не можете видеть замок, он скрыт внутри Windows. Более легко узнаваемый, который вы можете увидеть, находится внутри кода Winforms, который очищает очередь вызова. Требуется блокировка перед началом итерации этой очереди. Вы можете видеть это здесь, это - блокировка на элементе threadCallbackList.

Другие вопросы по тегам