-1

I have a thread that runs in the background during an asynchronous download. The purpose of the thread is to identify whether or not the download has stopped. My code basically says "if we haven't downloaded any more bytes in the last 10 seconds, assume the download has failed and do this".

When I tried to update a label on my WPF window saying the download had stopped, I was told I couldn't access it from a non-static reference. So I added MainWindow main = new MainWindow(), and then added that to the variable to keep from needing the WPF element to be static. But I also needed to use a Dispatcher because another thread already owned that object. So my code looked like this:

MainWindow main = new MainWindow();
main.Dispatcher.BeginInvoke(new Action(delegate() {
    main.mainTitle.Content = "Unable to connect to the internet";
}));

That didn't change anything though, so I changed my approach. I changed the Dispatcher to this:

MainWindow main = new MainWindow();
Application.Current.Dispatcher.BeginInvoke(new Action(delegate() {
    main.mainTitle.Content = "Unable to connect to the internet";
}));

However, this appeared to do nothing because on the line that changes the content of the WPF item, I received the error 'The calling thread cannot access this object because a different thread owns it.'

How can I change this object's content from another thread, and why isn't the Dispatcher working?

John Smith
  • 21
  • 4
  • 1
    `new MainWindow()` creates a new MainWindow instance, which is obviously not identical to the one that's already there. Use `(MainWindow)Application.Current.MainWindow` – Clemens Jul 08 '19 at 19:23
  • @Clemens You can't do that because that just casts the `Dispatcher` to become type `MainWindow` which you can't really do. – John Smith Jul 08 '19 at 19:28
  • 1
    Read my comment again, with a little more attention. – Clemens Jul 08 '19 at 19:33
  • 1
    Clemens is right, you don't want to `new` a Window here. Find a way to get a reference to the original MainWindow to the thread code, and then use Dispatcher.Invoke(). Application.Current looks fine, if it really is the Main window. – H H Jul 08 '19 at 19:40

1 Answers1

0

As I see this, you are trying to get some string into the MainWindow. The thing is, WPF starts with two Threads. The UI thread and the Render thread. The render thread starts rendering the WPF screen and the UI thread is responsible for inputs, handle events...

In your case, you need permission to access the UI thread from an other thread, you've created by yourself in code. My dispatcher looks like this:

System.Windows.Application.Current.Dispatcher.Invoke(delegate
{
     //your code to access property / variable / methods etc
});

Other way: Why aren't you using a pattern like MVVM with binding? If you would use binding, you could change the bound property and the value will update automatically in the UI. I'm not sure if the dispatcher is a way to access a WPF elements directly from an other thread.