WPF Dialog locks all threads
-
Ladies and Gentlemen, i have had something rear its ugly head today and I frankly do NOT for the life of me understand how this can be. After spending a couple of hours PROVING to myself (I am not always easily convinced) that what I am see is real, I scoured the net to the best of my googling abilities and came up empty. So I lay this at your feet hoping someone here has an answer. Naturally, I am on the customer site with a hard deadline and more than just my reputation at stake! I will spot you that I am NOT the most experienced Windows developer on this plant, but I have been around the block a few times. Here is my story. I have created a WPF application that is very much multi-threaded. In fact it is highly dependent on these threads. There are 5 main threads: 1) UI; 2) TCP/IP server; 3) GPIB client; 4) main application; and 5) the main application interface. When the app starts, MainWindow runs as with most WPF type apps. In the constructor I create some little class to do this and that and I instantiated each of the objects for the 4 main threads (obviously I am in the UI thread). Once the constructor is done the app drops into the normal sort of WPF wait for something to happen kind of thing. Meanwhile my other threads are busy handling comms, reading files and a variety of other things. When a particular msg arrives via TCP/IP the MainWindow is notified and he throws up a Window being used as a dialog. nothing fancy, just var dlg = new myWindow(); dlg.ShowDialog(); Here is where it gets REALLY weird! Every thread in the app stops! Freezes. Goes out to lunch! Describe how you wish. But they freeze. When the dialog is dismissed everybody goes about their business like nothing happened. Of course the reeks havoc on comm threads. Anybody and ANY ideas why this is happening?? And more to the point what the remedy is? Oh, I create my background threads using: Task.Factory.StartNew(() => { _pxiHandler.MainLoop(); }, TaskCreationOptions.LongRunning); TIA, Doug
I am a Traveler of both Time and Space
-
Ladies and Gentlemen, i have had something rear its ugly head today and I frankly do NOT for the life of me understand how this can be. After spending a couple of hours PROVING to myself (I am not always easily convinced) that what I am see is real, I scoured the net to the best of my googling abilities and came up empty. So I lay this at your feet hoping someone here has an answer. Naturally, I am on the customer site with a hard deadline and more than just my reputation at stake! I will spot you that I am NOT the most experienced Windows developer on this plant, but I have been around the block a few times. Here is my story. I have created a WPF application that is very much multi-threaded. In fact it is highly dependent on these threads. There are 5 main threads: 1) UI; 2) TCP/IP server; 3) GPIB client; 4) main application; and 5) the main application interface. When the app starts, MainWindow runs as with most WPF type apps. In the constructor I create some little class to do this and that and I instantiated each of the objects for the 4 main threads (obviously I am in the UI thread). Once the constructor is done the app drops into the normal sort of WPF wait for something to happen kind of thing. Meanwhile my other threads are busy handling comms, reading files and a variety of other things. When a particular msg arrives via TCP/IP the MainWindow is notified and he throws up a Window being used as a dialog. nothing fancy, just var dlg = new myWindow(); dlg.ShowDialog(); Here is where it gets REALLY weird! Every thread in the app stops! Freezes. Goes out to lunch! Describe how you wish. But they freeze. When the dialog is dismissed everybody goes about their business like nothing happened. Of course the reeks havoc on comm threads. Anybody and ANY ideas why this is happening?? And more to the point what the remedy is? Oh, I create my background threads using: Task.Factory.StartNew(() => { _pxiHandler.MainLoop(); }, TaskCreationOptions.LongRunning); TIA, Doug
I am a Traveler of both Time and Space
I suspect your background threads are running on a
TaskScheduler
which is tied to theDispatcher
of the UI thread. Try passingTaskScheduler.Default
to theTask.Factory.StartNew
method:Task.Factory.StartNew(_pxiHandler.MainLoop,
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);Obviously you'll need to make sure that any UI access or collection modification is posted to the UI thread.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
I suspect your background threads are running on a
TaskScheduler
which is tied to theDispatcher
of the UI thread. Try passingTaskScheduler.Default
to theTask.Factory.StartNew
method:Task.Factory.StartNew(_pxiHandler.MainLoop,
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);Obviously you'll need to make sure that any UI access or collection modification is posted to the UI thread.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Richard, thank you. Very much! An excellent suggestion! However after a sleepless night (anybody know why stuff like this always happens on site during acceptance testing?) a good friend this morning showed me error of my ways. You, see, the only problem was I have a wretched case of idiotitis. In my zeal to explore the nooks and crannies of this Windows world I made the decision that a nice clean way to allow objects to get information from other objects was exposé an event and delegate. Seemed reasonable to me at the time. Having spent most of my life in a world where objects on different threads have REAL boundaries I assumed that if some object from another thread registered a handler that naturally when that handler was invoked from thread 2 that the event would interrupt thread 1 it would process the event and thread 2 would go merrily on its way. Nope. Thread 2 runs the event handler. Well when the thread that is minding your comms is now suddenly executing code in MainWindow which consists of putting up a dialog guess who isn't watching his comms. Error of my ways #2 has to do with where one starts threads, which is the point you are making. I was informed that launching critical long running tasks from the MainWindow code was not a very good idea. Suggestion was to move them to the App class and override OnStartup. Which I have now done. That does create several questions but I will save them for another day. Error of my ways #3 was to foolishly mentally assign characteristics to objects in threads as I would to a process of lightweight thread in other operating systems. Not a good analogy. Sorry for the length but somebody out there will make the same boo-boo someday. Thank you again, Doug
I am a Traveler of both Time and Space