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

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

  •  01-09-2022
  •  | 
  •  

質問

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");
役に立ちましたか?

解決

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");

他のヒント

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;
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top