Application.Current.Shutdown() doesn't - wpf

Title's about it. WPF app with some WCF stuff for IPC. I call Application.Current.Shutdown() and the app continues on happily. I thought Shutdown was supposed to be unstoppable.
Perhaps because it's being called from a background thread? Do I need to do some dispatcher fiddling?

You get an exception when I call Application.Current.Shutdown in any thread other than the main one, so I'd assume you where using "dispatcher fiddling" properly already.
In any case, this compiles and quits an application, so if the dispatcher bit doesn't look like what you have you could sling it in:
ThreadStart ts = delegate()
{
Dispatcher.BeginInvoke((Action)delegate()
{
Application.Current.Shutdown();
});
};
Thread t = new Thread(ts);
t.Start();

In my experience all threads have to either be terminated explicitly or be marked as background threads in order for the application to close.
Here is an example of kicking off a read thread in the background:
_readThread = new Thread(new ThreadStart(ReadThread));
_readThread.Name = "Receiver";
_readThread.Priority = ThreadPriority.Highest;
_readThread.IsBackground = true;
_readThread.Start();
The IsBackground property is the key. Without that being set, the thread won't terminate on when you call Shutdown.

I only experience Application.Current.Shutdown not working when I'm running from Visual Studio. Within Visual Studio (at least the 2010 version I'm using) Application.Current.Shutdown doesn't do a thing. If I single step through it executes this line and then continues. If I run the program (as an .exe) from Windows Explorer then Application.Current.Shutdown works fine.
There is probably an explanation for this since during debug other threads are active, but I can't explain it.

Related

WPF BusyWindow unbreakable by main thread

How to create really unbreakable wpf busy window in separate thread?
Main thread run some a few second lasting intensive computation code. This code can not allow call UI refresh (DoEvents)(do not have cycle), and is not moveable to separate thread.
Busy Window have some spinner/progress, which should rotate/move. But it doesn't rotate/move if the main thread run intensive computation.
Most of "busy window in separate thread" - founded on web - do not work, if the main thread run intensive computation (nor Task, nor BackgroundWorker). Limitation is .net framework 4.0.
For testing, if I try to run intensive code in the main thread:
while(true) {}
then most web "busy window in separate thread" became blocked.
Best results I have with this code:
var thread = new Thread(new ThreadStart(() =>
{
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
asyncCtl = creator();
asyncCtl.CreateControl();
asyncCtl.Show();
System.Windows.Threading.Dispatcher.Run();
}));
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
Dispatcher.CurrentDispatcher.ShutdownStarted += CurrentDispatcher_ShutdownStarted;
Dispatcher.CurrentDispatcher.ShutdownFinished += CurrentDispatcher_ShutdownFinished;
When computation function finished, this code is called:
asyncCtl.Dispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
But - events ShutdownStarted / ShutdownFinished are called on main thread exits. This seems to me too late.
If application run BusyWindow 10 times, these events are called 10 times on main thread exits.
I afraid if there are 10 times shown BusyWindow, there stay hang 10 non-shutdowned threads which ends lately - on main application exits.
So, how to correctly create and dispose such busy window?
Thanks.

WPF: Wait animation window blocks

I have seen several similar questions on SO and elsewhere, but none seems to work for me.
I have a small Window in my project containing a LoadingAnimation that I show up at application startup and want to keep actual processing running. Here's my startup code:
Dim WaitWindow As New WaitWindow("Loading application...")
WaitWindow.Show()
LongRunningLoading()
WaitWindow.Close()
Here's LongRunningLoading() function that I try to run on a separate thread to avoid blocking my animation:
Private Function LongRunningLoading() As Boolean
Dim resetEvent As New System.Threading.ManualResetEvent(False)
Dim RetVal As Boolean = False
ThreadPool.QueueUserWorkItem(Sub(state)
'DO SOMETHING AND RETURN RESULTS
resetEvent.Set()
End Sub,
RetVal)
resetEvent.WaitOne()
Return RetVal
End Function
Everything works as expected except that the loading animation doesn't play. What am I doing wrong?
What am I doing wrong?
You're doing this:
resetEvent.WaitOne()
That blocks the UI thread. Don't do that. Instead, remember that the UI is basically event based - unless you're using the async features in VB 11, you'll have to write your code in an event-based way. So basically when your long-running task completes, you need to post back to the UI thread to execute the WaitWindow.Close() part.
If you can use .NET 4.5 and VB 11, you can use Task.Run to start a new task for your long-running work, and then Await that task from an asynchronous method.
They are both running on UI Thread, this is why loading animation is waiting. Try to use BackgroundWorker for your LongRunningLoading process and then return to UI thread if needed for your results.
This approach worked for me:
Dim waitwindow As New WaitWindow("Loading application...")
ThreadPool.QueueUserWorkItem( _
Sub()
LongRunningLoading()
Dispatcher.Invoke(New Action(AddressOf waitwindow.Close))
End Sub)
waitwindow.ShowDialog()
May help someone else.

TaskScheduler.FromCurrentSynchronizationContext - how to use WPF dispatcher thread when unit testing

I've got code in a ViewModel that calls a service through a task.
When the task finishes, it'll populate an ObservableCollection.
The problem is that it's waiting on the task to finish by using the ContinueWith method and providing TaskScheduler.FromCurrentSynchronizationContext as task scheduler, so that the OC gets updated on the UI thread.
So far so good, but when it comes to unit testing, it throws an exception saying that "the current SynchronizationContext may not be used as a TaskScheduler."
If I use a mock SynchronizationContext on the unit test, then the ObservableCollection throws an error because it's being updated based from the dispatcher thread.
Is there any way to work around this?
Thanks.
It's not exactly easy, but it's not really that hard either. What you need to do is a spin up a worker Thread that's setup as STA and you start up the Dispatcher runtime on it. Once you have that worker sitting there you can dispatch work to it from the unit test threads which are, obviously, not initialized for this kind of work. So, first, here's how you startup the dispatcher thread in your test setup:
this.dispatcherThread = new Thread(() =>
{
// This is here just to force the dispatcher infrastructure to be setup on this thread
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
Trace.WriteLine("Dispatcher worker thread started.");
}));
// Run the dispatcher so it starts processing the message loop
Dispatcher.Run();
});
this.dispatcherThread.SetApartmentState(ApartmentState.STA);
this.dispatcherThread.IsBackground = true;
this.dispatcherThread.Start();
Now, if you want to cleanly shut that thread down in your test cleanup, which I recommend you do, you simply do the following:
Dispatcher.FromThread(this.dispatcherThread).InvokeShutdown();
So, all that infrastructure stuff out of the way, here's all you need to do in your test to execute on that thread.
public void MyTestMethod
{
// Kick the test off on the dispatcher worker thread synchronously which will block until the work is competed
Dispatcher.FromThread(this.dispatcherThread).Invoke(new Action(() =>
{
// FromCurrentSynchronizationContext will now resolve to the dispatcher thread here
}));
}
Add this to your test initialisation, to create a context:
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
This makes it even simpler
TaskScheduler scheduler = Dispatcher.CurrentDispatcher.Invoke(TaskScheduler.FromCurrentSynchronizationContext)
you code can then use the scheduler explicitly (initialized with TaskScheduler.FromCurrentSynchronizationContext() during runtime)

Reliably Restart a Single-Instance WPF application

I would like to have my current application close and restart. I have seen many posts on this, however none of these seem to work for me.
I have tried
System.Diagnostics.Process.Start(System.Windows.Application.ResourceAssembly.Location);
System.Windows.Application.Current.Shutdown();
However this only restarts the application once. If I press my 'restart' button again (on the already restarted app), it only closes.
I have also tried launching a new System.Diagnostics.Process and closing the current process, but again this does not restart, it simply closes.
How can I restart my current WPF application?
You could create another application which you start when exiting your app and which in return does start your application again. Kind of like how a patcher would work, only without patching anything. On the plus side you could have a loop in that "restart-application" which checks all running processes for your main application process and only tries to re-start it once it does not appear in the process any longer - and you got the bare bones for a patcher also :) Whilst you do not seem to have a problem with restarting your application due to it still being in the processlist - it is the way I would go for when doing it in a production environment as this gives you the most control IMHO.
Edit:
That part in the button event handler (or wherever you want to restart your app with) of your main app (Process2BRestarted.exe in my case):
private void cmdRestart_Click(object sender, EventArgs e)
{
var info = new ProcessStartInfo();
info.FileName = "ProcessReStarter";
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info);
Application.Exit();
}
This should go into your utility/restarter application (ProcessReStarter.exe over here):
private void MainForm_Load(object sender, EventArgs e)
{
// wait for main application process to end
// really should implement some kind of error-checking/timer here also
while (Process.GetProcessesByName("Process2BRestarted").Count() > 0) { }
// ok, process should not be running any longer, restart it
Process.Start("Process2BRestarted");
// and exit the utility app
Application.Exit();
}
Clicking the restart button will now create a new process ProcessReStarter.exe, which will iterate through the process list of all running processes - checking whether Process2BRestarted is still running. If the process does not appear in the list (any longer) it will now start a new Process2BRestarted.exe process and exit itself.

Runtime debugging tips for Windows Service?

I have a Windows Service that monitors a COM port connected to a vendors hardware. This is a very busy piece of hardware that is constantly polling other devices on the wire (this is a twisted-pair RS485 "network"). My software needs to emulate X number of hardware devices on this wire, so I've got a multi-threaded thing going on with a multi-tiered state machine to keep track of where the communications protocol is at any moment.
Problem is with a Windows Service (this is my first one, BTW) is that you need some debugging to let you know if stuff is working properly. When I was first developing this state machine/multi-thread code I had a windows form with a RichTextBox that displayed the ASCII chars going back-n-forth on the line. Seems like I can't really have that GUI niceness with a service. I tried opening a form in the service via another program that sent the service messages that are received via the OnCustomCommand() handler but it didn't seem to work. I had "Allow service to interact with desktop" checked and everything. I was using the Show() and Hide() methods of my debug form.
I guess I don't need to see all of the individual characters going on the line but man that sure would be nice (I think I really need to see them :-) ). So does anyone have any crazy ideas that could help me out? I don't want to bog down the system with some IPC that isn't meant for the voluminous amount of data that is sure to come through. It will only be very short-term debugging though, just confirmation that the program, the RS485-to-USB dongle, and hardware is all working.
Use OutputDebugString to write to the debugging buffer and then use DebugView to watch it. If you're running on Windows XP or earlier, then you can use PortMon to see the raw bytes going through the serial port. The advantage over a log file is that there's very little overhead, particularly when you're not watching it. You can even run DebugView from another machine and monitor your service remotely.
I dunno if it will work for you, but I always build my services with a extra Main that build them as console app to get debug output.
Edit:
Some example:
class Worker : ServiceBase
{
#if(RELEASE)
/// <summary>
/// The Main Thread where the Service is Run.
/// </summary>
static void Main()
{
ServiceBase.Run(new Worker());
}
#endif
#if(DEBUG)
public static void Main(String[] args)
{
Worker worker = new Worker();
worker.OnStart(null);
Console.ReadLine();
worker.OnStop();
}
#endif
// Other Service code
}
You could write the output to a log file and then use another application to watch that file. This question about "tail" outlines several options for watching log files with windows.
What I usually do when working on a Windows Service is to create it so that it can be run either as a service, or as a plain old command-line application. You can easily check whether you are running as a service by checking Environment.UserInteractive. If this property is true, then you are running from the command line. If the property is false, then you are running as a service. Add this code to Program.cs, and use it where you would normally call ServiceBase.Run(servicesToRun)
/// <summary>Runs the provided service classes.</summary>
/// <param name="servicesToRun">The service classes to run.</param>
/// <param name="args">The command-line arguments to pass to the service classes.</param>
private static void RunServices(IEnumerable<ServiceBase> servicesToRun, IEnumerable args)
{
var serviceBaseType = typeof(ServiceBase);
var onStartMethod = serviceBaseType.GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var service in servicesToRun)
{
onStartMethod.Invoke(service, new object[] { args });
Console.WriteLine(service.ServiceName + " started.");
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
var onStopMethod = serviceBaseType.GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var service in servicesToRun)
{
onStopMethod.Invoke(service, null);
Console.WriteLine(service.ServiceName + " stopped.");
}
}
Now you can debug your service, set breakpoints, anything you want. When you run your application, you'll get a console window, appropriate for displaying console messages, and it will stay open until you hit a key.
I'm answering my own question here. I tried a couple of suggestions here but here's what I ended up doing...
I created a Windows Form application with a single Button and RichTextBox. This application constructed a NamedPipeServerStream on it's end. The Button's job was to send either "debug on" (command 128) or "debug off" (129) to the Windows Service. The initial value was "debug off". When the button was clicked, a command of 128 was sent to the Windows Service to turn debugging on. In the Windows Service this triggered an internal variable to be true, plus it connected to the Form application with a NamedPipeClientStream and started sending characters with a BinaryWriter as they were received or sent on the COM port. On the Form side, a BackgroundWorker was created to WaitForConnection() on the pipe. When it got a connection, a BinaryReader.ReadString() was used to read the data off of the pipe and shoot it to the RichTextBox.
I'm almost there. I'm breaking my pipe when I click the debug button again and a subsequent click doesn't correctly redo the pipe. All in all I'm happy with it. I can post any code if anyone is interested. Thanks for the responses!

Resources