System.InvalidOperationException и System.Reflection.TargetInvocationException иногда происходят - PullRequest
1 голос
/ 19 февраля 2010

Когда я запускаю свою программу, иногда я получаю эти исключения, а иногда нет.Это поток выполнения:

Пользователь нажимает кнопку в классе Window1.
Класс собирает входные данные, запускается backgroundWorker.RunWorkerAsync ().
В DoWork App.doStuff () имеет значениес именем.
Внутри App.doStuff () я создаю другой поток, чтобы показать индикатор выполнения в другом окне, например:

Thread newWindowThread =  new Thread(new ThreadStart(showProgressMethod));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();

В showProgressMethod () я делаю:

progressWindow = new MyProgressWindow(this);
progressWindow.Show();
System.Windows.Threading.Dispatcher.Run();

Теперь, если я запускаю его впервые, у меня никогда не будет проблем.Но когда / если я повторяю операцию после ее завершения, я могу получить исключения.

Глядя на код, я чувствую, что делаю что-то не так, вызывая dispatcher.Run () иThread.Start (), но я плохо понимаю модель потоков, поэтому я не уверен.

В любом случае, при первом запуске программа никогда не делает ничего необычного.Но иногда, когда я снова нажимаю кнопку, чтобы активировать процесс, возникает исключение.Я думаю, что это происходит, когда у программы не было достаточно времени для очистки?Хотя я не уверен.

РЕДАКТИРОВАТЬ

Кажется, что проблема в том, что поток ProgressWindow не заканчивается.Очевидно, что добавление Thread.Abort () внутри App.doStuff () или Dispatcher.Thread.Abort () внутри ProgressWindow решает проблему.Видимо.

Но все еще возникают исключения из-за метода Abort (), хотя он больше не падает.Я также не понимаю, почему закрытие ProgressWindow не завершает поток.И из того, что я прочитал с помощью Thread.Abort (), не очень хорошая практика, хотя опять же я не понимаю, почему.

EDIT 2

Thread.Abortвсе еще имел сбой время от времени.Итак, что я сделал:
Замените Show() вызов на ShowDialog(), как предложено, и
Удалите вызов для System.Windows.Threading.Dispatcher.Run();

Ответы [ 3 ]

0 голосов
/ 20 февраля 2010

a) TargetInvocationException станет настоящим исключением в свойстве InnerException - проверьте это.

б) Вы уверены, что не используете / не трогаете объекты из двух разных потоков? WPF явно выбрасывает, если он обнаруживает свойство зависимости, к которому обращаются из потока, отличного от того, в котором свойство зависимости было создано.

0 голосов
/ 20 февраля 2010

Пользователь нажимает кнопку в классе Window1. Класс собирает входные данные, запускается backgroundWorker.RunWorkerAsync (). В DoWork вызывается App.doStuff (). Внутри App.doStuff () я создаю другой поток, чтобы показать индикатор выполнения ...

Итак, теперь у вас есть код, выполняющийся в потоке пользовательского интерфейса, код, выполняющийся в потоке BackgroundWorker, и код, выполняющийся в новом, третьем потоке, который не является потоком пользовательского интерфейса и обновляет элементы пользовательского интерфейса. У меня есть это право? Потому что это звучит так, как будто это почти наверняка проблема.

Edit:

Я удивлен, что то, что вы делаете, работает вообще, а не работает непоследовательно.

Событие ProgressChanged в BackgroundWorker - это то, что вы хотите использовать для взаимодействия между методом, работающим в фоновом режиме, и пользовательским интерфейсом. Он работает в потоке пользовательского интерфейса.

0 голосов
/ 19 февраля 2010

Что внутри MyProgressWindow?Может быть, он получает доступ к некоторым ResourceDictionary дважды, один раз из первого newWindowThread, один раз из второго?ResourceDictionary s не могут быть разделены между двумя потоками.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...