Reputation: 1153
I'm working on a user control for UWP and it updates some of its visuals upon certain calls. However, since the core .NET library has been shifted around and the threading classes have been severely cut back, I don't know how to identify from the method in the user control if the calling thread is the UI thread or not so it knows whether or not to use the dispatcher to change a dependency property.
Anyone know how to do this?
EDIT: The dispatcher functionally can be "invoked" async fine on the UI thread - however, I really don't know if this is a good idea - to try to invoke on the main thread from the main thread via the dispatcher. If anyone has a reason this is fine or bad, that would also contribute to answering the question. If there's no reason to not use the dispatcher on the main thread, then I guess there's no problem.
Upvotes: 17
Views: 8581
Reputation:
My son just encountered this as an Issue so I thought I would add an updated answer.
The Main UI thread can be accessed using the Core Dispatcher CoreWindow.GetForCurrentThread().Dispatcher
or Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher
Below is a class that implements the Core Dispatcher
and tests whether the calling thread is the Main UI Thread. If so it invokes the action, otherwise calls Dispatcher.RunAsync
to execute it on the Main UI thread.
class Threading {
private static CoreDispatcher Dispatcher =>
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
public static async void ThreadSafe(DispatchedHandler action)
{
// Calls Dispatcher.RunAsync to run a method on the Main UI Thread
IAsyncAction UiThread(DispatchedHandler proc) => Dispatcher.RunAsync(CoreDispatcherPriority.Normal, proc);
// Checks to see if this was called from the Main UI thread
// If we are in the Main UI thread then Invoke the action
// Otherwise: Send it to run in the Main Ui Thread.
if (Dispatcher.HasThreadAccess) { action.Invoke(); } else { await UiThread(action); };
}
}
The above class could be used like so:
// Some event handler callback
private void SomeCallback(object sender)(){
void line() => Frame.Navigate(typeof(PageName));
Threading.ThreadSafe(line);
}
// Pass a handle to the control and a string to update it's text property
internal static void ChangeControlText(dynamic ctrl , string v)
{
void line() {ctrl.Text= v;}
ThreadSafe(line);
}
Upvotes: 2
Reputation: 1153
I have found the solution...
CoreDispatcher.HasThreadAccess returns a bool indicating if you are on the UI thread or not.
Upvotes: 22