Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#中使用BackgroundWorker?_C#_Windows_Multithreading - Fatal编程技术网

在C#中使用BackgroundWorker?

在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,我有两个问题:

1) 假设有函数A和函数B。函数A创建了一个运行函数B的BackgroundWorker。因此BackgroundWorker现在在一个单独的线程上运行函数B。函数B是一个无限while循环,我打算长时间运行它。函数A通过使用BackgroundWorker后,返回。既然启动BackgroundWorker的函数(函数A)已经返回,那么BackgroundWorker线程是否仍在后台运行?或者它停止运行函数B,因为实例化它的函数已返回?如果它真的停止了,我将如何使它即使在函数A返回后也能继续运行呢

2) 我需要从BackgroundWorker创建的单独线程访问窗口窗体项(即文本框)。但是,如果尝试从非主线程访问窗口窗体项,则会出现跨线程错误。如何从单独的线程安全地访问窗口窗体项?我基本上需要从一个单独的线程中不断更新文本框。我知道BackgroundWorker有一个名为“RunWorkerCompleted”的成员,该成员在BackgroundWorker完成其工作后运行。它允许我从此访问窗口窗体项目。但是,我需要在线程期间而不是在线程完成后访问窗口窗体项。如何通过线程安全地访问这些?如果这是不可能的,还有什么其他可能的解决方案吗?

1)函数A返回后,
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是在另一个线程中创建的,因此导致了跨线程错误。