繁体   English   中英

我如何调用从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事件中引发异常:

treeView1.Nodes.Add(CreateDirectoryNode(root, "root"));

出现InvalidOperationException

正在从错误的线程调用对此控件执行的操作。 使用Control.Invoke或Control.BeginInvoke编组到正确的线程以执行此操作

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”));

您不能直接从非UI线程修改UI元素。 使用BackgroundWorker ,修改UI线程的最佳位置是来自ProgressChangedRunWorkerCompleted事件。

首先,通过RunWorkerAsync()方法从UI中传递值:

backgroundWorker1.RunWorkerAsync(txtHost.Text);

仅在DoWork事件中执行非UI的工作,然后将结果传递给RunWorkerCompleted事件:

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时,该应用程序可能会暂时冻结,但是您不会收到该特定异常。

DoWork事件在后台线程中运行。 它不能与UI元素进行交互。 您应该创建一些结果; 本身不是UI元素的东西,将其设置为BGW的Result属性,然后在RunWorkerCompleted偶数处理程序中基于该结果更新UI,可以访问DoWork的结果集。

暂无
暂无

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

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