WPF - Невозможно изменить свойство GUI внутри метода OnChanged (запущено из FileSystemWatcher)

Я хочу изменить свойство GUI в методе OnChanged... (в действительности я пытаюсь установить источник изображения, но для простоты здесь используется кнопка). Это называется everytime filesystemwatcher обнаруживает изменение в файле.. и он попадает в "верхний" вывод.. но получает исключение, когда пытается установить ширину кнопки.

но если я ставлю один и тот же код на кнопку, он работает нормально. Я искренне не понимаю, почему.. кто-нибудь может мне помочь?

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

то, что я действительно пытаюсь сделать, вместо изменения ширины кнопки:

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

Ответ 1

Проблема в том, что это событие возникает в фоновом потоке. Вам нужно перевести вызов обратно в поток пользовательского интерфейса:

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

Ответ 2

Я предполагаю, что FileSystemWatcher вызывает ваш обработчик событий в другом потоке. Внутри обработчика событий используйте приложение Dispatcher для его возврата в поток пользовательского интерфейса:

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

private void DoSomethingOnUiThread() {
    Test_Button.Width = 500;
}