简体   繁体   中英

How can i invoke a method called from backgroundworker dowork event?

This is the method:

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

Then in background do work:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {            
            var root = txtHost.Text;
            treeView1.Nodes.Clear();            
            treeView1.Nodes.Add(CreateDirectoryNode(root, "root"));           
        }

And the progresschanged:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.toolStripProgressBar2.Value = Math.Min(this.toolStripProgressBar2.Maximum, e.ProgressPercentage);
        }

After 20 seconds of work it throw exception in the DoWork event on the line:

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

InvalidOperationException

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: 

Line 419 is: treeView1.Nodes.Add(CreateDirectoryNode(root, "root"));

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.

First, pass the values from the UI via the RunWorkerAsync() method:

backgroundWorker1.RunWorkerAsync(txtHost.Text);

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

Subscribe to the RunWorkerCompleted event to update the UI:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    var dirNode = (TreeNode)e.Result;

    treeView1.Nodes.Clear(); 

    treeView1.Nodes.Add(dirNode);
}

The app may freeze momentarily while the TreeView is being updated in the RunWorkerCompleted event, but you won't get that particular exception.

The DoWork event runs in a background thread. It cannot interact with UI elements. You should be creating some result; something that is not itself a UI element, setting it to the BGW's Result property, and then updating the UI based on that result in the RunWorkerCompleted even handler, which can access the result set in DoWork .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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