在C#中使用BackgroundWorker?
关于使用BackgroundWorker,我有两个问题: 1) 假设有函数A和函数B。函数A创建了一个运行函数B的BackgroundWorker。因此BackgroundWorker现在在一个单独的线程上运行函数B。函数B是一个无限while循环,我打算长时间运行它。函数A通过使用BackgroundWorker后,返回。既然启动BackgroundWorker的函数(函数A)已经返回,那么BackgroundWorker线程是否仍在后台运行?或者它停止运行函数B,因为实例化它的函数已返回?如果它真的停止了,我将如何使它即使在函数A返回后也能继续运行呢 2) 我需要从BackgroundWorker创建的单独线程访问窗口窗体项(即文本框)。但是,如果尝试从非主线程访问窗口窗体项,则会出现跨线程错误。如何从单独的线程安全地访问窗口窗体项?我基本上需要从一个单独的线程中不断更新文本框。我知道BackgroundWorker有一个名为“RunWorkerCompleted”的成员,该成员在BackgroundWorker完成其工作后运行。它允许我从此访问窗口窗体项目。但是,我需要在线程期间而不是在线程完成后访问窗口窗体项。如何通过线程安全地访问这些?如果这是不可能的,还有什么其他可能的解决方案吗?1)函数A返回后,在C#中使用BackgroundWorker?,c#,windows,multithreading,C#,Windows,Multithreading,关于使用BackgroundWorker,我有两个问题: 1) 假设有函数A和函数B。函数A创建了一个运行函数B的BackgroundWorker。因此BackgroundWorker现在在一个单独的线程上运行函数B。函数B是一个无限while循环,我打算长时间运行它。函数A通过使用BackgroundWorker后,返回。既然启动BackgroundWorker的函数(函数A)已经返回,那么BackgroundWorker线程是否仍在后台运行?或者它停止运行函数B,因为实例化它的函数已返回?如
BackgroundWorker
将继续运行
2) 创建更新文本框的
ProgressChanged
事件处理程序,并在需要更改文本时调用BackgroundWorker
调用ReportProgress
。当然,您必须让BackgroundWorker
设置一个ProgressChanged
事件可以读取的属性。这是因为在UI线程上调用了ProgressChanged
事件处理程序。Jim的回答是正确的。
在第二部分,你说
我需要从BackgroundWorker创建的单独线程访问窗口窗体项(即文本框)
所以现在如果你只想这样做,那么你需要做的就是创建一个扩展方法,如下所示
public static class ControlExtensions
{
public static void Invoke(this Control control, Action action)
{
if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null);
else action.Invoke();
}
}
现在,当您从非UI线程访问文本框时,您需要这样做
txtBox.Invoke(() => { txtBox.Text = "Text Changed from Non-UI thread"; });
希望这对您有所帮助。关于第二个问题: 就连我也曾经面对过同样的问题。因此使用了“工作法”。
这就是我的工作方式
private void bgwLongTask_DoWork(object sender, DoWorkEventArgs e)
{
my long task
{
//in between the long task, i want to udpate the datagrid view dataGridView1
if (dataGridView1.InvokeRequired)
dataGridView1.Invoke(myGridBindDelegate);
else
BindDataToGrid();
}
}
这里myGridBindDelegate是调用datagrid视图绑定方法的委托
delegate void GridBindDelegate();
GridBindDelegate myGridBindDelegate;
myGridBindDelegate = BindDataToGrid;
private void BindDataToGrid()
{
dataGridView1.DataSource = dt; //dt is a datatable which is public
dataGridView1.Refresh();
}
为我工作。谢谢。我使用ProgressChanged,但它仍然给我一个跨线程错误。知道为什么吗?@Amir Palsapure谢谢你的帮助。你的答案对我来说有点太复杂了(不是你的错),而这一个似乎更简单,所以我决定试试。我刚开始写C#,所以这个答案似乎更容易理解。再次感谢您的帮助。在哪个线程上挂接了事件处理程序。它应该在UI线程上。换句话说,在绑定事件处理程序之前,您说的是WorkAsync()。查看博客以了解cross thread issue.ad 1)>BackgroundWorker将继续运行,但您需要在某处保留对它的引用。否则它迟早会被垃圾收集。谢谢,它工作得很好。它以前不工作,因为我刚刚意识到BackgroundWorker是在另一个线程中创建的,因此导致了跨线程错误。