如何调用从backgroundworker dowork事件调用的方法? [英] How can i invoke a method called from backgroundworker dowork event?

查看:376
本文介绍了如何调用从backgroundworker dowork事件调用的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是方法:

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线程的最佳位置是ProgressChangedRunWorkerCompleted事件.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆