BackgroundWorker в событии Form.Load - PullRequest
0 голосов
/ 14 марта 2012

Я работаю в приложении ac # windows с vs2010 и локальной базой данных. В одной из моих форм я использую BindingNavigator с группой текстовых полей, заполненных базой данных, и ReporViewer.Я добавил фонового работника для заполнения таблицы адаптеров на случай, если в базе данных много записей.

Проблема в том, что при использовании отладчика в фоновом режиме я не вижу никаких данных в текстовых полях, в противном случае, когда я запускаю свое приложение, оно работает нормально.Я знаю, что это случай доступа к пользовательскому интерфейсу в потоке без пользовательского интерфейса, и это неправильно.Есть ли другой способ обойти это? Спасибо заранее.

Вот код, который я использую:

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

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    this.clientTableAdapter.Fill(this.database1DataSet.Client);
    this.projectTableAdapter.Fill(this.database1DataSet.Project);

    if (InvokeRequired)
    {
        this.Invoke(new MethodInvoker(this.reportViewer1.RefreshReport));
        return;
    }
}

1 Ответ

1 голос
/ 14 марта 2012

Как правило, фоновый работник возвращается в тот же поток и на самом деле выдает исключение для потока, не являющегося пользовательским интерфейсом. Тем не менее, это может быть съедено в вашем случае. Вы должны использовать событие RunWorkerCompleted для элементов, которые должны произойти после того, как ваша основная работа завершена, особенно когда вы хотите обновить пользовательский интерфейс. И этот должен возвращаться в тот же поток, из которого он был вызван (пользовательский интерфейс в вашем случае), как упомянуто выше.

Итак, я бы переместил ваш код обработки пользовательского интерфейса (RefreshReport) в новый метод, настроенный для RunWorkerCompleted.

Однако, я бы посоветовал взглянуть на Task Parallel Library . В итоге код становится намного чище и проще для отладки IMO.

Пример (грубый и может не скомпилироваться из-за пустых значений, но вы можете получить jist:)):

var task = Task.Factory.StartNew(()=>{//Do Async Stuff});
task.ContinueWith((previousTask)=>{//Do your UI Stuff}, null, null, 
    TaskScheduler.FromCurrentSynchronizationContext);
//The FromCurrentSync makes sure the method returns 
//to the same thread (UI in this case) that it started

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

...