25 March, 2009

WPF: InvokeRequired = !Dispatcher.CheckAccess()

Update (05.03.2011):
Since this post, .NET 4 has arrived. The <Control>.Dispatcher.CheckAccess() is now made available in Intellisense (in VS).  In addition, an easier code construct than the initial version, is the below (note: ‘btnSplit’ is a Button in this case):

private void HandleUIButtons()
{
if (!btnSplit.Dispatcher.CheckAccess())
{
//if here - we are on a different non-UI thread
btnSplit.Dispatcher.BeginInvoke(new Action(HandleUIButtons));
}
else
btnSplit.IsEnabled = true; //this is ultimately run on the UI-thread
}

----------


Original post:
Doing some multithreading coding in WPF – I again today stumbled upon the missing InvokeRequired functionality known from WinForms coding. The InvokeRequired bool property on a control that is used when doing mulithreaded WinForms coding, has been replaced by the Dispatcher.CheckAccess() method call in WPF.


Be aware that the old property (InvokeRequired) returned true if the calling thread was different from the owning thread; whereas the Dispatcher.CheckAccess() methodcall returns true if the calling thread is the SAME as the owning thread. In other words – the response is reversed so to speak.


Note: The Dispathcer.CheckAccess() method does NOT show up in Visual Studio due to a System.ComponentModel.EditorBrowsableState.Never method attribute in the source code from Microsofts hand!


void PopulatePage()
{
//check whether the calling thread is the thread owning the txtDBConn control
if (!txtDBConn.Dispatcher.CheckAccess())
{
var popAct = new Action(PopulatePage);
txtDBConn.Dispatcher.BeginInvoke(popAct, System.Windows.Threading.DispatcherPriority.DataBind, null);
}
else
{

this.txtDBConn.Text = ConfigurationManager.ConnectionStrings[Constants.Database.DB_CONN].ConnectionString;
}
}

6 comments:

JM said...

Damn, you saved my life:

I have an application mixing Forms and WPF and my thread protection functions were:

public delegate void InvokeHandler();
public static void UiInvoke(this System.Windows.Forms.Control control, InvokeHandler handler) {
if (control.InvokeRequired)
control.Invoke(handler);
else
handler();
}

//Extension method to invoke UI if in a different thread (WPF)
public static void UiDispatch(this System.Windows.Controls.Control control, InvokeHandler handler) {
if (control.CheckAccess())
control.Dispatcher.Invoke(handler);
else
handler();
}

Imagine the time I lost befroe to add the little "!" that changed all :)

Thks

Claus Konrad said...

Glad it helped you as well!

jesper said...

Jeg skulle også lige bruge den gode gamle InvokeRequired i WPF, men den var væk! Tak for hjælpen.

Anonymous said...

Hello! Probably, Microsoft doesn't want developers to use Dispatcher.CheckAccess(). Taking into account that all

controls, including page, are created inside the UI thread, inside a page constructor the property

Thread.CurrentThread.ManagedThreadId is the required UI thread identifier. We can use this fact it in the next way:

using System;
using Microsoft.Phone.Controls;

namespace WindowsPhoneApplication1
{
public partial class MainPage : PhoneApplicationPage
{
private int _uiThreadID = -1;

private bool IsUIThread
{
get { return _uiThreadID == System.Threading.Thread.CurrentThread.ManagedThreadId; }
}

// Constructor
public MainPage()
{
// preserve UI thread id
_uiThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
InitializeComponent();
}

public void UpdateSomeTextBox(string text)
{
if (IsUIThread) // if it's UI thread, just set the new text directly
someTextBox.Text = text;
else // otherwise, invoke UpdateSomeTextBox in UI thread
Dispatcher.BeginInvoke(delegate()
{
UpdateSomeTextBox(text);
});
}
}
}

I've described it in details in my post in blog here http://dotnetfollower.com/wordpress/2011/07/silverlight-for-

windows-phone-7-how-to-check-if-the-current-thread-is-ui-one/

Thank you!
.Net Follower (http://dotnetfollower.com)

Tony Sneed said...

As far as I'm concerned, there isn't any reason you should not call Dispatcher.CheckAccess, even though it doesn't show up in Intellisense. Just because the method is marked as EditorBrowsable(Never) does not mean that Microsoft does not want you to use it -- it may simply be because of a bug in Visual Studio Intellisense. See the documentation for Dispatcher.CheckAccess: http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.checkaccess.aspx.

net performance said...

I did a search on the topic and found mainly persons will agree with your blog.The main thing about the article its that You made certain fine points there.