1

So I have a program that works as the UI for a console app. I tried to add a progress bar to it. When the user clicks on the Start button, it does this:

MainProgress.Value = 0;
MainProgress.Maximum = PackageNwCheckbox.IsChecked == true ? 4 : 3;
BackgroundWorker compilerWorker = new BackgroundWorker();
compilerWorker.WorkerReportsProgress = true;
compilerWorker.DoWork += StartCompiler;
compilerWorker.ProgressChanged += CompilerReport;
compilerWorker.RunWorkerAsync();

This is in order to update the progress bar when the GUI program works and feeds the console program. When the program starts populating the array called filemap like this:

filemap = Directory.GetFiles(ProjectLocation.Text + "\\www\\js\\", "*.js");
//The variable is an array of strings.

The app crashes and the error says

The call thread couldn't access the item because another thread has it.

Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
acemod13
  • 55
  • 8
  • Possible duplicate of [The calling thread cannot access this object because a different thread owns it](https://stackoverflow.com/questions/9732709/the-calling-thread-cannot-access-this-object-because-a-different-thread-owns-it) – Victor Procure Aug 29 '18 at 14:30
  • Since you are using the `BackgroundWorker` you'll want to only interact with the UI elements from your CompilerReport method, or you'll need to pass the object value in the `RunWorkerAsync()` method. See https://stackoverflow.com/a/6481328/252458 for a bit more info – KSib Aug 29 '18 at 14:36

2 Answers2

1

In desktop applications with background threads, if you're attempting to update a view. You will need to invoke that update with the dispatcher. Somewhere in your CompilerReport method you want something like this:

MainProgress.Dispatcher.Invoke(() =>
{
    // Do update here
});

With more code, I could probably detail a better answer

Victor Procure
  • 886
  • 1
  • 6
  • 17
1

You can't access ProjectLocation.Text from a background thread. You can only access members of a UI control on the thread on which it was originally created.

So if you want the current text of ProjectLocation in your DoWork event handler, you should use the dispatcher:

string location = Dispatcher.Invoke(() => ProjectLocation.Text);
filemap = Directory.GetFiles(location + "\\www\\js\\", "*.js");

Or pass it as an argument to the RunWorkerAsync method.

mm8
  • 163,881
  • 10
  • 57
  • 88