Укрощение строптивого BackgroundWorker
От: user485  
Дата: 20.10.11 10:43
Оценка:
Возникла такая проблема. Время от времени, BackgroundWorker.RunWorkerCompleted вызывается не из потока, который создал объект (как должно быть), а из других потоков.
Тестовый код такой:

Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);
var worker = new BackgroundWorker();
worker.DoWork += (s, args) => Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);
worker.RunWorkerCompleted += (s, args) => Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);
worker.RunWorkerAsync();


Выдает например такую фигню: 10 6 11
(должно быть 10 6 10)

Есть идеи, в чем причина?
Re: Укрощение строптивого BackgroundWorker
От: rumatavz  
Дата: 20.10.11 13:03
Оценка: 16 (2) +2
Причина в том, что BackgroundWorker.RunWorkerCompleted не должен вызывается из потока, который создал объект.
Он должен вызываться с тем же контекстом синхронизации, в котором работал поток, создавший объект. Если контекст синхронизации есть, то эти два высказывания эквивалентны. А вот если контекста синхронизации нет, то BackgroundWorker.RunWorkerCompleted вызывается из потока из пула.
Re[2]: Укрощение строптивого BackgroundWorker
От: user485  
Дата: 21.10.11 03:59
Оценка:
Здравствуйте, rumatavz, Вы писали:

R>Он должен вызываться с тем же контекстом синхронизации, в котором работал поток, создавший объект. Если контекст синхронизации есть, то эти два высказывания эквивалентны. А вот если контекста синхронизации нет


А где и как он устанавливается?
Re[3]: Укрощение строптивого BackgroundWorker
От: rumatavz  
Дата: 21.10.11 06:59
Оценка: +1
Здравствуйте, user485, Вы писали:

U>Здравствуйте, rumatavz, Вы писали:


R>>Он должен вызываться с тем же контекстом синхронизации, в котором работал поток, создавший объект. Если контекст синхронизации есть, то эти два высказывания эквивалентны. А вот если контекста синхронизации нет


U>А где и как он устанавливается?


У вас есть поток, который исполняет некий код, в этом потоке вы создаете воркера, и хотите чтоб по завершению работы один из методов воркера выполнился в исходном потоке. Проблема в том, что в вашем потоке продолжает исполнятся какой то другой код. То есть по сути дела метод воркера должен как бы вклинится в исполняющийся в потоке код в случайном месте. Это не возможно. А если бы и было возможно, то было бы ничем не лучше, чем если бы этот метод выполнился в другом потоке.

С гуевым потоком совсем другая история. В гуёвом потоке есть цикл обработки сообщений, и если мы хотим выполнить метод в этом потоке, то просто добавляем сообщение в очередь. В какой то момент оно обработается. При его обработке будет вызван тот метод, который требовалось. Здесь не требуется никакого вклинивания в случайный момент времени.

Расскажите плз, какую задачу вы решаете, т.к. наиболее вероятно, что здесь вообще не нужен BackgroundWorker.
Re[4]: Укрощение строптивого BackgroundWorker
От: user485  
Дата: 21.10.11 08:44
Оценка:
Здравствуйте, rumatavz, Вы писали:

R>У вас есть поток, который исполняет некий код, в этом потоке вы создаете воркера, и хотите чтоб по завершению работы один из методов воркера выполнился в исходном потоке. Проблема в том, что в вашем потоке продолжает исполнятся какой то другой код. То есть по сути дела метод воркера должен как бы вклинится в исполняющийся в потоке код в случайном месте. Это не возможно. А если бы и было возможно, то было бы ничем не лучше, чем если бы этот метод выполнился в другом потоке.


R>С гуевым потоком совсем другая история. В гуёвом потоке есть цикл обработки сообщений, и если мы хотим выполнить метод в этом потоке, то просто добавляем сообщение в очередь. В какой то момент оно обработается. При его обработке будет вызван тот метод, который требовалось. Здесь не требуется никакого вклинивания в случайный момент времени.


Мимо. Основной поток, который создает воркера — GUI, никакими долгими задачами он не занят.

R>Расскажите плз, какую задачу вы решаете, т.к. наиболее вероятно, что здесь вообще не нужен BackgroundWorker.


Нужно выполнить большой и сложный код, который включает вычисления и обращения к сети.
Re[5]: Укрощение строптивого BackgroundWorker
От: rumatavz  
Дата: 23.10.11 07:29
Оценка:
В момент выполнения этого кода контрол уже отображается в ГУИ?
Re[5]: Укрощение строптивого BackgroundWorker
От: Abalak США  
Дата: 24.10.11 04:09
Оценка:
Здравствуйте, user485, Вы писали:

R>>Расскажите плз, какую задачу вы решаете, т.к. наиболее вероятно, что здесь вообще не нужен BackgroundWorker.


U>Нужно выполнить большой и сложный код, который включает вычисления и обращения к сети.


BackgroundWorker и Control.Invoke() спасет отца демократии. И все равно из какого потока пойдет сообщение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.