WPF Dispatcher.CheckAccess() vs Windows Forms Control.InvokeRequired

Coloro che utilizzano quotidianamente le Windows Forms conosceranno il significato della property InvokeRequired nell’ambito della classe Windows.Forms.Control. Sappiamo infatti che i controlli di una Windows Forms sono legati ad uno specifico thread (generalmente il main thread) e non sono thread safe. Per questo motivo, se intendiamo invocare un qualsiasi metodo su un controllo oppure modificare una sua property (es. modificare il testo di una label o di una textbox) da un thread differente, è necessario invocare uno dei metodi che permettono di eseguire il marshal nel thread giusto. Questi ultimi sono : Invoke() per l’invocazione sincrona, BeginInvoke() e EndInvoke() per un’invocazione asincrona.

La property InvokeRequired ci permette di capire se è necessario eseguire questa operazione di marshal in un altro thread o meno. Per questo motivo, quando bisogna intervenire tipicamente sulla UI, all’interno del nostro metodo adottiamo un codice di questo tipo :

if (this.myControl.InvokeRequired)
{
    // accesso indiretto attraverso Invoke() o BeginInvoke()
    this.myControl.Invoke(.....);
}
else
{
    // accesso diretto a myControl
    this.myControl.SomeMethod();
    this.myControl.SomeProperty = value;
}

Ma esiste in WPF una controparte della InvokeRequired ?

In WPF, ogni controllo ha la property Dispatcher sulla quale è possibile invocare i medesimi metodi Invoke() e BeginInvoke() per eseguire il marshal nel thread giusto. Sempre Dispatcher fornisce la controparte della InvokeRequired, ossia il metodo CheckAccess() che ritorna true se l’invocazione avviene già nel thread giusto. Per questo motivo il codice suddetto diventa :

if (this.myControl.Dispatcher.CheckAccess())
{
    // accesso diretto a myControl
    this.myControl.SomeMethod();
    this.myControl.SomeProperty = value;
}
else
{
    // accesso indiretto attraverso Invoke() o BeginInvoke()
    this.myControl.Dispatcher.Invoke(.....);
}

E’ importante sottolineare che se in Visual Studio provate a farvi aiutare dall’Intellisense, il metodo CheckAccess() non vi verrà mostrato ma se lo scrivete senza alcun aiuto e compilate, tutto funzionerà correttamente. La sua invisibilità è dovuta alla sua dichiarazione :

[EditorBrowsable(EditorBrowsableState.Never)]
public bool CheckAccess();

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s