Если я использую BackgroundWorker для изменения структур данных в моем приложении, есть ли гарантия, что изменения, сделанные в фоновом потоке, будут видны в основном потоке (UI) при завершении BackgroundWorker (например, в обработчике событий RunWorkerCompleted)? Для бонусных очков: если да, то каков механизм, который это гарантирует?Предоставляет ли BackgroundWorker, что изменения в памяти, сделанные в фоновом потоке, становятся видимыми для основного потока?
ответ
Нет, таких гарантий не существует. Вам нужно будет синхронизировать доступ к любой разделяемой памяти самостоятельно, если вы хотите получить к ней доступ из нескольких потоков.
Конечно, если вы используете встроенные механизмы BGW для передачи данных между потоками, например, через данные, хранящиеся в Result
или Progress
, то он будет правильно синхронизировать доступ к этим данным.
Да, это не то, о чем вам нужно беспокоиться, пока вы будете следовать контракту BackgroundWorker. Другими словами, используйте предоставленные события для передачи данных в поток пользовательского интерфейса, ProgressChanged и RunWorkerCompleted. Исходный код .NET Framework не начисляет баллов за это, синхронизация не является явной. Это довольно распространено, во многих местах он использует неявную синхронизацию.
Но есть два, которые гарантируют, что поток пользовательского интерфейса может видеть обновления. Во-первых, это функция PostMessage(), функция winapi, которая используется для сигнатуры потока пользовательского интерфейса, который необходимо просмотреть в очереди вызовов. Used here, вы, тем не менее, не видите замок вообще, он похоронен внутри Windows. Более легко узнаваемый, который вы можете получить в . Код находится внутри кода Winforms, который освобождает очередь вызова. Он занимает блокировку, прежде чем он начнет повторять эту очередь. Вы можете видеть it here, это замок на threadCallbackList участник.