Причина в том, что BackgroundWorker.RunWorkerCompleted не должен вызывается из потока, который создал объект.
Он должен вызываться с тем же контекстом синхронизации, в котором работал поток, создавший объект. Если контекст синхронизации есть, то эти два высказывания эквивалентны. А вот если контекста синхронизации нет, то BackgroundWorker.RunWorkerCompleted вызывается из потока из пула.
Здравствуйте, user485, Вы писали:
U>Здравствуйте, rumatavz, Вы писали:
R>>Он должен вызываться с тем же контекстом синхронизации, в котором работал поток, создавший объект. Если контекст синхронизации есть, то эти два высказывания эквивалентны. А вот если контекста синхронизации нет
U>А где и как он устанавливается?
У вас есть поток, который исполняет некий код, в этом потоке вы создаете воркера, и хотите чтоб по завершению работы один из методов воркера выполнился в исходном потоке. Проблема в том, что в вашем потоке продолжает исполнятся какой то другой код. То есть по сути дела метод воркера должен как бы вклинится в исполняющийся в потоке код в случайном месте. Это не возможно. А если бы и было возможно, то было бы ничем не лучше, чем если бы этот метод выполнился в другом потоке.
С гуевым потоком совсем другая история. В гуёвом потоке есть цикл обработки сообщений, и если мы хотим выполнить метод в этом потоке, то просто добавляем сообщение в очередь. В какой то момент оно обработается. При его обработке будет вызван тот метод, который требовалось. Здесь не требуется никакого вклинивания в случайный момент времени.
Расскажите плз, какую задачу вы решаете, т.к. наиболее вероятно, что здесь вообще не нужен BackgroundWorker.
Возникла такая проблема. Время от времени, 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)
Здравствуйте, rumatavz, Вы писали:
R>Он должен вызываться с тем же контекстом синхронизации, в котором работал поток, создавший объект. Если контекст синхронизации есть, то эти два высказывания эквивалентны. А вот если контекста синхронизации нет
Здравствуйте, rumatavz, Вы писали:
R>У вас есть поток, который исполняет некий код, в этом потоке вы создаете воркера, и хотите чтоб по завершению работы один из методов воркера выполнился в исходном потоке. Проблема в том, что в вашем потоке продолжает исполнятся какой то другой код. То есть по сути дела метод воркера должен как бы вклинится в исполняющийся в потоке код в случайном месте. Это не возможно. А если бы и было возможно, то было бы ничем не лучше, чем если бы этот метод выполнился в другом потоке.
R>С гуевым потоком совсем другая история. В гуёвом потоке есть цикл обработки сообщений, и если мы хотим выполнить метод в этом потоке, то просто добавляем сообщение в очередь. В какой то момент оно обработается. При его обработке будет вызван тот метод, который требовалось. Здесь не требуется никакого вклинивания в случайный момент времени.
Мимо. Основной поток, который создает воркера — GUI, никакими долгими задачами он не занят.
R>Расскажите плз, какую задачу вы решаете, т.к. наиболее вероятно, что здесь вообще не нужен BackgroundWorker.
Нужно выполнить большой и сложный код, который включает вычисления и обращения к сети.
Здравствуйте, user485, Вы писали:
R>>Расскажите плз, какую задачу вы решаете, т.к. наиболее вероятно, что здесь вообще не нужен BackgroundWorker.
U>Нужно выполнить большой и сложный код, который включает вычисления и обращения к сети.
BackgroundWorker и Control.Invoke() спасет отца демократии. И все равно из какого потока пойдет сообщение.