WPF - Cannot change a GUI property inside the OnChanged method (fired from FileSystemWatcher)

StackOverflow https://stackoverflow.com/questions/20575277

  •  01-09-2022
  •  | 
  •  

Question

I want to change a GUI property in the OnChanged method... (in actuality im trying to set an image source.. but used a button here for simplicity). This is called everytime filesystemwatcher detects a change in a file.. and it gets to the "top" output.. but catches an exception when it tries to set the button width.

but if i put the same code in a button.. it works just fine. I sincerely don't understand why.. can someone help me?

private void OnChanged(object source, FileSystemEventArgs e)
        {
            //prevents a double firing, known bug for filesystemwatcher
            try
            {
                _jsonWatcher.EnableRaisingEvents = false;
                FileInfo objFileInfo = new FileInfo(e.FullPath);
                if (!objFileInfo.Exists) return;   // ignore the file open, wait for complete write

                //do stuff here                    
                Console.WriteLine("top");
                Test_Button.Width = 500;
                Console.WriteLine("bottom");
            }
            catch (Exception)
            {
                //do nothing
            }
            finally
            {
                _jsonWatcher.EnableRaisingEvents = true;
            }
        }

what i'm really trying to do instead of changing a button width:

BlueBan1_Image.Source = GUI.GetChampImageSource(JSONFile.Get("blue ban 1"), "avatar");
Was it helpful?

Solution

The problem is that this event is raised on a background thread. You need to marshal the call back to the UI thread:

// do stuff here                    
Console.WriteLine("top");
this.Dispatcher.BeginInvoke(new Action( () =>
{
    // This runs on the UI thread
    BlueBan1_Image.Source = GUI.GetChampImageSource(JSONFile.Get("blue ban 1"), "avatar");
    Test_Button.Width = 500;
}));
Console.WriteLine("bottom");

OTHER TIPS

I'm guessing that the FileSystemWatcher is calling your event handler on another thread. Inside your event handler, use your application's Dispatcher to marshal it back to the UI thread:

private void OnChanged(object source, FileSystemEventArgs e) {
    Application.Current.Dispatcher.BeginInvoke(new Action(() => DoSomethingOnUiThread()));
}

private void DoSomethingOnUiThread() {
    Test_Button.Width = 500;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top