如何调用从backgroundworker dowork事件调用的方法? [英] How can i invoke a method called from backgroundworker dowork event?
问题描述
这是方法:
private TreeNode CreateDirectoryNode(string path, string name)
{
var directoryNode = new TreeNode(name);
var directoryListing = GetDirectoryListing(path);
var directories = directoryListing.Where(d => d.IsDirectory);
var files = directoryListing.Where(d => !d.IsDirectory);
foreach (var dir in directories)
{
i ++;
directoryNode.Nodes.Add(CreateDirectoryNode(dir.FullPath, dir.Name));
int percentage = (i + 1) * 100 / 100;
backgroundWorker1.ReportProgress(percentage);
}
foreach (var file in files)
{
directoryNode.Nodes.Add(new TreeNode(file.Name));
}
return directoryNode;
}
然后在后台运行:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var root = txtHost.Text;
treeView1.Nodes.Clear();
treeView1.Nodes.Add(CreateDirectoryNode(root, "root"));
}
进度改变了
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.toolStripProgressBar2.Value = Math.Min(this.toolStripProgressBar2.Maximum, e.ProgressPercentage);
}
工作20秒后,它在以下行的DoWork事件中引发异常:
After 20 seconds of work it throw exception in the DoWork event on the line:
treeView1.Nodes.Add(CreateDirectoryNode(root, "root"));
InvalidOperationException
InvalidOperationException
正在从错误的线程调用对此控件执行的操作.使用Control.Invoke或Control.BeginInvoke编组到正确的线程以执行此操作
Action being performed on this control is being called from the wrong thread. Marshal to the correct thread using Control.Invoke or Control.BeginInvoke to perform this action
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=Action being performed on this control is being called from the wrong thread. Marshal to the correct thread using Control.Invoke or Control.BeginInvoke to perform this action.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.TreeNode.Realize(Boolean insertFirst)
at System.Windows.Forms.TreeNodeCollection.AddInternal(TreeNode node, Int32 delta)
at FTP_ProgressBar.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in c:\ftp_progressbar\FTP_ProgressBar\Form1.cs:line 419
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
InnerException:
第419行是:treeView1.Nodes.Add(CreateDirectoryNode(root,"root"));
Line 419 is: treeView1.Nodes.Add(CreateDirectoryNode(root, "root"));
推荐答案
您不能直接从非UI线程修改UI元素.使用BackgroundWorker
时,修改UI线程的最佳位置是ProgressChanged
或RunWorkerCompleted
事件.
You can't directly modify UI elements from a non-UI thread. When using a BackgroundWorker
, the best place to modify the UI thread is from the ProgressChanged
or RunWorkerCompleted
events.
首先,通过RunWorkerAsync()
方法从用户界面传递值:
First, pass the values from the UI via the RunWorkerAsync()
method:
backgroundWorker1.RunWorkerAsync(txtHost.Text);
仅在DoWork
事件中执行非UI的工作,然后将结果传递给RunWorkerCompleted
事件:
Only do non-UI work in the DoWork
event, then pass the results to the RunWorkerCompleted
event:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var root = Convert.ToString(e.Argument); // txtHost.Text;
var dirNode = CreateDirectoryNode(root, "root");
e.Result = dirNode;
}
订阅RunWorkerCompleted
事件以更新UI:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var dirNode = (TreeNode)e.Result;
treeView1.Nodes.Clear();
treeView1.Nodes.Add(dirNode);
}
在RunWorkerCompleted
事件中更新TreeView时,该应用程序可能会暂时冻结,但是您不会收到该特定异常.
The app may freeze momentarily while the TreeView is being updated in the RunWorkerCompleted
event, but you won't get that particular exception.
这篇关于如何调用从backgroundworker dowork事件调用的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!