#c# #backgroundworker
#c# #backgroundworker
Вопрос:
Я пытаюсь следовать примеру BackgroundWorker, приведенному здесь http://msdn.microsoft.com/en-us/library/wkays279.aspx под заголовком «Возврат значений из многопоточных процедур»
Я поместил трудоемкий вызов базы данных в обработчик событий DoWork BackgroundWorker. Я ожидаю, что как только я вызову BackgroundWorkerAsync (object), этот вызов произойдет в фоновом режиме и не заблокирует выполнение остальной части приложения. Проблема в том, что этого не происходит. Все приложение блокируется и ожидает возврата вызова базы данных. Как только он возвращается, приложение снова реагирует.
Вот мой код
//initialization in a method.
Worker.DoWork = new DoWorkEventHandler(Worker_DoWork);
Worker.RunWorkerCompleted = new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
Retriever temp = (Retriever)e.Argument;
e.Result = temp.RetrieveLongDBCallThatReturnsADataSet() //App blocks until done.
}
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
System.Data.DataSet result = (System.Data.DataSet)e.Resu<
//Do stuff with the DataSet.
}
public void Retrieve(object arg1, object arg2, object arg3)
{
Retriever temp = new Retriever();
InitializeBackgroundWorker(); //wire up events
temp.Prop1 = arg1;
temp.Prop2 = arg2;
temp.Prop3 = arg3;
Worker.RunWorkerAsync(temp);
//Code that is expected to start executing, but instead blocks until temp.RetrieveLongDBCallThatReturnsADataSet() finishes.
}
Кто-нибудь может увидеть, чего мне здесь не хватает? Я проделал то же самое с вызовом веб-сервиса, и это, кажется, работает нормально.
Комментарии:
1. Осуществляется ли доступ к базе данных в другом месте? Это действительно
DoWork
вызов, который блокирует основной пользовательский интерфейс? (Может ли это быть отвлекающим маневром?)2. Спасибо за ответ pst. Я не уверен, понял ли я ваш вопрос. Вы имеете в виду, есть ли другой процесс, вызывающий базу данных, пока я вызываю RunWorkerAsync? Я не вижу, чтобы к БД обращались в другом месте. Из любопытства я закомментировал этот вызов DB в классе Retriever и заменил его на While (true) { } После того, как я это сделал, фоновый рабочий повел себя так, как я ожидал. Приложение не заблокировалось, несмотря на этот бесконечный цикл.
3. Что вы делаете в
RetrieveLongDBCallThatReturnsADataSet
? Вероятно, в этом и заключается проблема…4.
//Code that is expected to start executing
. Там не должно быть кода. Переместите его в обработчик событий RunWorkerCompleted.
Ответ №1:
Этого не должно произойти, если:
Вы ожидаете результата базы данных (или чего-то, что блокирует поток пользовательского интерфейса) в следующих строках после DoWork
асинхронного вызова.
Поместите Break Point
в следующую строку после вызова RunWorkerAsync
, и вы должны немедленно получить поток (или добавьте этот код к своему вопросу)
Комментарии:
1. — Спасибо за ваш ответ. Интересно… Я установил точку останова сразу после вызова RunWorkAsync и сразу же перешел к следующей строке. Вот где я запутался. Строка после этой следующей строки является Form.ShowDialog(). Эта форма не является взаимодействием / ожиданием с результатами DB, которые я ожидаю получить, но эта форма блокируется. Все, для чего предназначена эта форма, это прокручивать индикатор выполнения, пока возвращаются результаты. Затем RunWorkerEventCompleted закрывает эту форму.
2. Похоже, проблема в коде, который вы не показываете. Как вы обновляете индикатор выполнения и что вы подразумеваете под «этой формой блоков»? Он полностью не отвечает / не обновляет индикатор выполнения / вы можете переместить его, но он не отображает элементы управления?
3. Спасибо всем за ваши ответы. Оказывается, это был код, который выполнялся после запуска события RunWorkerCompleted. Меня сбило с толку то, что форма все еще отображалась на экране во время выполнения кода после события RunWorkerCompleted. Код в событии RunWorkerCompleted, в частности, закрыл форму. Единственное, о чем я могу думать, это о какой-то проблеме с перерисовкой. Добавление точек останова дальше по потоку показало мне, какой код блокировался. Я перенес этот код в BackgroundWorker и теперь получаю результаты, которые я ожидал. Спасибо всем, кто откликнулся.