简体   繁体   English

在C#中使用BackgroundWorker?

[英]Using BackgroundWorker in C#?

I have two questions about using a BackgroundWorker: 关于使用BackgroundWorker,我有两个问题:

1)Lets say you have Function A and Function B. Function A creates a BackgroundWorker which runs Function B. So the BackgroundWorker is now running Function B on a separate thread. 1)假设您具有函数A和函数B。函数A创建了一个运行函数B的BackgroundWorker。因此BackgroundWorker现在在单独的线程上运行函数B。 Function B is an infinite while loop that I intend to run for a long duration. 函数B是一个无限的while循环,我打算长时间运行。 After Function A uses the BackgroundWorker through, it returns. 函数A通过使用BackgroundWorker之后,将返回。 So now that the function that initiated the BackgroundWorker (Function A) has returned, does the BackgroundWorker thread keep running in the background? 那么,既然启动了BackgroundWorker的函数(函数A)已经返回,BackgroundWorker线程是否继续在后台运行? Or does it stop running Function B since the function that instantiated it has returned? 还是因为实例化的函数返回而停止运行函数B? If it does stop, how would I make it so that Function B continues to run even after Function A has returned? 如果它确实停止了,我该如何做,以使功能B即使在功能A返回后也能继续运行?

2)I need to access Window Forms Items (ie Textbox) from a separate thread created by a BackgroundWorker. 2)我需要从BackgroundWorker创建的单独线程访问“窗口表单项”(即“文本框”)。 However if I try to access Window Forms Items from a thread that is not main, I get a cross threading error. 但是,如果尝试从不是主线程的线程访问“窗口表单项”,则会收到跨线程错误。 How could I safely access Window Forms Items from a separate thread? 如何从一个单独的线程安全地访问“窗口表单项”? I basically need to keep updating a textbox from a separate thread. 我基本上需要继续从单独的线程更新文本框。 I know a BackgroundWorker has a member called "RunWorkerCompleted" and that is run after the BackgroundWorker completes its job. 我知道BackgroundWorker有一个名为“ RunWorkerCompleted”的成员,该成员在BackgroundWorker完成其工作之后运行。 It allows me to access Window Forms Items from this. 它允许我从中访问“窗口表单项”。 However, I need to access a Window Forms Item during the duration of my thread rather than after its completion. 但是,我需要在线程期间而不是完成之后访问“窗口表单项”。 How could I access these safely through a thread? 我如何通过线程安全地访问它们? If this isn't possible what are some other possible solutions to the problem? 如果这不可能,那么有什么其他可能的解决方案呢?

1) The BackgroundWorker will continue to run after Function A returns. 1)函数A返回后, BackgroundWorker将继续运行。

2) Create a ProgressChanged event handler that updates the text box, and have the BackgroundWorker call ReportProgress whenever you want to change the text. 2)创建一个ProgressChanged事件处理程序以更新文本框,并在每次您要更改文本时让BackgroundWorker调用ReportProgress Of course, you'll have to make the BackgroundWorker set a property that the ProgressChanged event can read. 当然,您必须使BackgroundWorker设置一个ProgressChanged事件可以读取的属性。 This works because the ProgressChanged event handler is called on the UI thread. 之所以可行,是因为在UI线程上调用了ProgressChanged事件处理程序。

The answer by Jim is correct. 吉姆的答案是正确的。

In part two, you said 在第二部分中,您说

I need to access Window Forms Items (ie Textbox) from a separate thread created by a BackgroundWorker. 我需要从BackgroundWorker创建的单独线程访问“窗口表单项”(即“文本框”)。

So now if you want to do this way only then you will need to do is create an extension method like below 因此,现在,如果您只想这样做,那么您需要做的就是创建一个如下所示的扩展方法

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();
    }
}

Now when you are accessing the text box from your Non-UI thread, you will need to do it like this 现在,当您从Non-UI线程访问文本框时,您需要这样做

txtBox.Invoke(() => { txtBox.Text = "Text Changed from Non-UI thread"; });

Hope this helps you. 希望这对您有所帮助。

For the second question: 对于第二个问题:

Even i faced the same problem once. 甚至我也曾经遇到过同样的问题。 So used the _DoWork method. 因此使用了_DoWork方法。
This is how it worked for me 这就是我的工作方式

 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();
     }
 }

Here myGridBindDelegate is the delegate which calls the datagrid view binding method. 在这里,myGridBindDelegate是调用datagrid视图绑定方法的委托。

    delegate void GridBindDelegate();
    GridBindDelegate myGridBindDelegate;
    myGridBindDelegate = BindDataToGrid;

    private void BindDataToGrid()
    {
        dataGridView1.DataSource = dt; //dt is a datatable which is public
        dataGridView1.Refresh();
    }

Worked for me. 为我工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM