When running my program, sometimes I get these exceptions, other times I don't. This is the flow of execution:
User clicks a button in the Window1 class.
Class collects inputs, backgroundWorker.RunWorkerAsync() is started. In the DoWork, App.doStuff() is called. Inside App.doStuff(), I create another thread to show a progressbar in a different window like this:Thread newWindowThread = new Thread(new ThreadStart(showProgressMethod));
newWindowThread.SetApartmen开发者_运维问答tState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
In the showProgressMethod(), I do:
progressWindow = new MyProgressWindow(this);
progressWindow.Show();
System.Windows.Threading.Dispatcher.Run();
Now, if I'm running it for the first time, I never have any problems. But when/if I redo the operation once it's completed, then I might get the exceptions.
Looking at the code, I get the feeling I'm doing something wrong by calling the dispatcher.Run() and the Thread.Start(), but I don't understand the threading model well, so I'm not sure.
Either way, on the first run, the program never does anything unusual. But sometimes when I click the button again to activate the process, then the exception occurs. I think it happens when the program hasn't had enough time to clean up? I'm not sure though.
EDIT
Seems that the problem is that the ProgressWindow thread isn't ending. Apparently adding a Thread.Abort() inside App.doStuff() or Dispatcher.Thread.Abort() inside the ProgressWindow fixes the problem. Apparently.
But, it's still raising exceptions because of the Abort() method, though it no longer crashes. I also don't understand why closing the ProgressWindow doesn't end the thread. And from what I've read using Thread.Abort() isn't good practice though again I don't understand why.
EDIT 2
Thread.Abort still had it crashing at times. So, what I've done is:
Replace theShow()
call for ShowDialog()
, as suggested and
Remove the call for the System.Windows.Threading.Dispatcher.Run();
What is inside MyProgressWindow
? Maybe it accesses some ResourceDictionary
twice, once from first newWindowThread
, once from second? ResourceDictionary
s cannot be shared between two threads.
a) TargetInvocationException will the real exception in the InnerException property -- inspect that.
b) are you sure you aren't reusing/touching objects from two different threads? WPF explicitly throws if it detects a dependency property being accessed from a thread other than the one the dependencyproperty it was created on.
User clicks a button in the Window1 class. Class collects inputs, backgroundWorker.RunWorkerAsync() is started. In the DoWork, App.doStuff() is called. Inside App.doStuff(), I create another thread to show a progressbar...
So now you have code running on the UI thread, code running on the BackgroundWorker thread, and code running on a new, third thread, one that's not the UI thread, and that's updating UI elements. Do I have that right? Because that sounds like it's almost certainly a problem.
Edit:
I'm surprised that what you're doing works at all, not that it works inconsistently.
The ProgressChanged
event of the BackgroundWorker
is what you want to use for interoperation between the method running in the background and the user interface. It runs on the UI thread.
精彩评论