While working on a WPF application, I had a need to show the wait cursor while performing a long running operation. You would expect the code to look as follows:
System.Windows.Input.Cursor previousCursor = someWindow.Cursor;
someWindow.Cursor = System.Windows.Input.Cursors.Wait;
try
{
LongRunningOperation();
}
finally
{
someWindow.Cursor = previousCursor;
}
However, I didn't want the long running process tying up the UI thread. I needed to run the long running operation on its own thread. I decided to use the Task Parallel Library (TPL) to help.
System.Windows.Input.Cursor previousCursor = someWindow.Cursor;
someWindow.Cursor = System.Windows.Input.Cursors.Wait;
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
LongRunningOperation();
}).ContinueWith((t) =>
{
someWindow.Dispatcher.BeginInvoke(new Action(() => someWindow.Cursor = previousCursor));
});
Note that I had to use Dispatcher.BeginInvoke since the ContinueWith code is running on another thread.
After writing this code, I quickly realized that I could use this functionality in multiple places. Therefore, I came up with the following helper method:
code>
using System;
using System.Threading.Tasks;
using System.Windows.Input;
...
public Task ShowWaitCursorWhile(this FrameworkElement element, Action action)
{
Cursor previousCursor = this.Owner.Cursor;
element.Cursor = Cursors.Wait;
return Task.Factory.StartNew(() =>
{
action();
}).ContinueWith((t) =>
{
element.Dispatcher.BeginInvoke(new Action(() => element.Cursor = previousCursor));
});
}
...
This seemed like useful code, so I figured I'd throw it out here so that others may benefit from it. Since I am doing Model-View-View Model (MVVM) development, I will probably try to find a way to abstract this into a separate utility that can then be mocked out when testing. That way my view model won't be coupled to the view or its particular cursor/wait implementation.