C # BackgroundWorker блокирует вызов базы данных в обработчике DoWork

#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 и теперь получаю результаты, которые я ожидал. Спасибо всем, кто откликнулся.