Почему мой backgroundWorker не работает? - PullRequest
1 голос
/ 17 мая 2011

Я пытался внедрить фоновый рабочий, но он не работает во втором потоке, а форма все еще блокируется, и я не могу вызвать событие моей кнопки 2, кто-то скажет мне, почему это происходит?

мой код:

public Form1()
{
  InitializeComponent();
  backgroundWorker1.DoWork += 
    new DoWorkEventHandler(backgroundWorker1_DoWork);
  backgroundWorker1.ProgressChanged += 
    new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
  backgroundWorker1.RunWorkerCompleted += 
    new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
  backgroundWorker1.WorkerReportsProgress = true;
}

void backgroundWorker1_RunWorkerCompleted(object sender, 
  RunWorkerCompletedEventArgs e)
{
  MessageBox.Show("Work is done");
}

void backgroundWorker1_ProgressChanged(object sender, 
  ProgressChangedEventArgs e)
{
  this.progressBar1.Value = e.ProgressPercentage;
}

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
  ThreadProc();
}

private void button1_Click(object sender, EventArgs e)
{
  backgroundWorker1.RunWorkerAsync();
}

void ThreadProc()
{
  //simulate work
  for (int i = 0; i < 100000; ++i)
  {
    int total = i / 1000;
    backgroundWorker1.ReportProgress(total);
  }
}

private void button2_Click(object sender, EventArgs e)
{
  MessageBox.Show("Another thread");
}

ТКС;

Ответы [ 3 ]

4 голосов
/ 17 мая 2011

Похоже, вы можете сообщать о прогрессе обратно в форму с очень высокой скоростью, что приведет к блокировке формы.

Попробуйте изменить метод ThreadProc следующим образом ... только для демонстрационных целей:

void ThreadProc ()
{
    //simulate work
    for ( int i = 0; i < 100000; ++i )
    {
        Thread.Sleep( 1 ); // this should allow the form to breath a little :)
        int total = i / 1000;
        backgroundWorker1.ReportProgress( total );
    }
}
1 голос
/ 17 мая 2011

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

Поскольку ProgressBar.Value является int, это не должно отличаться:

  for (int i = 0; i < 100; i++)
  {
    backgroundWorker1.ReportProgress(i);
  }
0 голосов
/ 17 мая 2011

Для начала могу сказать, что фоновый рабочий будет в другом потоке, выделенном из ThreadPool. Тем не менее, все еще возможно заблокировать ваш пользовательский интерфейс, потому что когда вы вызываете события ProgressChanged или RunWorkerCompleted, они перенаправляются обратно в поток пользовательского интерфейса. Только событие DoWork работает в другом потоке ThreadPool.

Если вы не в потоке пользовательского интерфейса, вы не сможете получить доступ к элементам пользовательского интерфейса, например к кнопке 2, без небольшой дополнительной работы. Чтобы получить доступ к элементам пользовательского интерфейса из других потоков, необходимо использовать Control.Invoke для перенаправления обратного вызова в поток пользовательского интерфейса.

...