C # вызывает backgroundWorker из другого потока, чем поток пользовательского интерфейса - PullRequest
4 голосов
/ 22 декабря 2010

Я пытаюсь загрузить loadingForm, как показано ниже.Но это не работает, loadForm не исчезает, событие RunWorkerCompleted не вызывается.

И еще мне нужно звонить loadingForm и backgroundWorker несколько раз, так как мне полностью утилизировать loadingForm и backgroundWorker после каждого вызова?

Я думаю, что в моем коде много неправильного, но я не знаю, как это исправить.Не могли бы вы показать мне, как решить мою проблему и указать, где мне нужно исправить?Заранее большое спасибо.

public partial class loginForm : Form
{
     //....
     private loadingForm lf;
     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
     {
          lf.Show();
          While (backgroundWorker1.isBusy)
               Application.DoEvents();
     }
     private void backgroundWorker1_RunWorkerCompleted(object sender, DoWorkEventArgs e)
     {
          lf.Close();
     }
     private void connect()
     {
          //....
          Thread mainThread = new Thread(ThreadStart(listentoServer));
          mainThread.Start();
     }
     private void listentoServer()
     {
          //....
          lf = new loadingForm();
          backgroundWorker1.RunWorkerAsync();
          //....
          backgroundWorker1.CancelAsync();
          //.... 
     }
}

Ответы [ 3 ]

3 голосов
/ 22 декабря 2010

С вашим кодом много чего не так. Если можете, попробуйте сделать шаг назад и опишите, что именно вы хотите сделать.

BackgroundWorker использует основанный на событиях асинхронный шаблон (EAP). Как таковой, он требует контекста потока для жизни. Потоки пользовательского интерфейса удовлетворяют этому требованию, но созданные вручную Thread экземпляры этого не делают (если только вы не установите один или не сделаете экземпляр вторичным потоком пользовательского интерфейса).

Аналогично, компоненты пользовательского интерфейса привязываются к определенному потоку. Им требуется поток STA, который выполняет прокачку сообщений (например, Application.DoEvents).

Мне кажется, что вы создаете руководство Thread, а затем создаете компоненты пользовательского интерфейса из этого потока (так что вы знаете, что поток должен быть STA , а включает цикл прокачки сообщений, ни один из которые есть в вашем коде). Затем этот поток запускает BGW, который отправляет сообщения.

Непонятно, чего вы здесь добиваетесь - возможно, отображение диалога в отдельной теме?

Несколько потоков пользовательского интерфейса в приложении WinForms не являются официально поддерживаемым сценарием AFAIK, хотя некоторые люди заставили его работать. Я никогда не видел в этом необходимости.

1 голос
/ 22 декабря 2010

Я действительно не знаю, как исправить ваш код окончательно, или если ваш код даже работает так, как у вас, я могу дать вам только следующее руководство.

  1. использовать CancellationPending свойство фонового работника, а не свойство IsBusy
  2. при работе с формами Windows и многопоточным кодом всегда используйте методы Invoke / BeginInvoke , чтобы убедиться, что вы перенаправили свой вызов обратно в поток, из которого был создан элемент управления.
1 голос
/ 22 декабря 2010

Согласно тому, что вы показали (что, по общему признанию, является неполным, так что это может быть не проблемой), вы не подключаете свое событие к обработчикам событий backgroundWorker_DoWork и backgroundWorker_RunWorkerCompleted.Где-то (после того, как вы создадите экземпляр backgroundWorker), у вас должно быть следующее:

backgroundWorker.DoWork += new EventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new EventHandler(backgroundWorker_RunWorkerCompleted);

В качестве отказа от ответственности это было написано от руки, поэтому имена событий или типы EventHandler могут быть неправильными.

...