Detecting whether on UI thread in WPF and Winforms
Solution 1:
Don't use
if(Dispatcher.CurrentDispatcher.Thread == Thread.CurrentThread)
{
// Do something
}
Dispatcher.CurrentDispatcher
will, if the current thread do not have a dispatcher, create and return a new Dispatcher
associated with the current thread.
Instead do like this
Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
if (dispatcher != null)
{
// We know the thread have a dispatcher that we can use.
}
To be sure you have the correct dispatcher or are on the correct thread you have the following options
Dispatcher _myDispatcher;
public void UnknownThreadCalling()
{
if (_myDispatcher.CheckAccess())
{
// Calling thread is associated with the Dispatcher
}
try
{
_myDispatcher.VerifyAccess();
// Calling thread is associated with the Dispatcher
}
catch (InvalidOperationException)
{
// Thread can't use dispatcher
}
}
CheckAccess()
and VerifyAccess()
do not show up in intellisense.
Also, if you have to resort to these kinds of things its likely due to bad design. You should know which threads run what code in your program.
Solution 2:
Within WinForms you would normally use
if(control.InvokeRequired)
{
// Do non UI thread stuff
}
for WPF
if (!control.Dispatcher.CheckAccess())
{
// Do non UI Thread stuff
}
I would probably write a little method that uses a Generic constraint to determine which of these you should be calling. e.g.
public static bool CurrentlyOnUiThread<T>(T control)
{
if(T is System.Windows.Forms.Control)
{
System.Windows.Forms.Control c = control as System.Windows.Forms.Control;
return !c.InvokeRequired;
}
else if(T is System.Windows.Controls.Control)
{
System.Windows.Controls.Control c = control as System.Windows.Control.Control;
return c.Dispatcher.CheckAccess()
}
}
Solution 3:
For WPF, I use the following:
public static void InvokeIfNecessary (Action action)
{
if (Thread.CurrentThread == Application.Current.Dispatcher.Thread)
action ();
else {
Application.Current.Dispatcher.Invoke(action);
}
}
The key is instead of checking Dispatcher.CurrentDispatcher (which will give you the dispatcher for the current thread), you need to check if the current thread matches the dispatcher of the application or another control.
Solution 4:
For WPF:
// You are on WPF UI thread!
if (Thread.CurrentThread == System.Windows.Threading.Dispatcher.CurrentDispatcher.Thread)
For WinForms:
// You are NOT on WinForms UI thread for this control!
if (someControlOrWindow.InvokeRequired)