Background.Load事件中的BackgroundWorker

时间:2012-03-14 13:55:41

标签: c# .net thread-safety sql-server-ce backgroundworker

我正在使用vs2010和本地数据库在c#windows应用程序中工作。在我的一个表单中,我使用BindingNavigator和一组由数据库填充的文本框和一个ReporViewer。我已经添加了一个后台工作程序,以便在数据库中有大量记录的情况下填充表适配器。

问题是当我调试我的应用程序时我使用后台工作者的方式我无法在文本框中看到任何数据,否则当我运行我的应用程序时它工作正常。我知道这是在非UI线程上访问UI的情况,这是错误的。还有另外一种方法吗?提前谢谢你。

以下是我正在使用的代码:

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 个答案:

答案 0 :(得分:1)

通常,后台工作程序返回同一个线程,实际上会抛出有关非UI线程的异常。但是,这可能会在您的情况下吃掉。对于在主要工作完成后要发生的项目,您应该使用RunWorkerCompleted事件,尤其是在查看更新UI时。而且,如上所述, 应该返回到它所调用的同一个线程(在你的情况下是UI)。

因此,我会将您的UI处理代码(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

我知道这不是一个直接的答案,而是更多关于我认为更清洁,更可调试的方法的建议。