[英]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.