如何判断当前线程是否为UI线程?

17

我正在为UWP开发用户控件,当某些调用发生时它会更新一些可视化元素。然而,由于核心的.NET库已经被重构,线程类也被严重削减,所以我不知道如何从用户控件的方法中识别调用线程是否是UI线程,以便确定是否使用调度程序更改一个依赖属性。

有人知道如何做到这一点吗?

编辑:调度程序在UI线程上可以“异步”地被调用,但是我真的不知道这样做是否明智——尝试通过调度程序从主线程上调用主线程。如果有人有这样做好或坏的原因,那么这也有助于回答问题。如果没有理由不在主线程上使用调度程序,那么我想就没有问题了。


你不能总是调用 RunAsync 吗? - Alexei Levenkov
4
@X-TECH 不太可能是正确的重复项 - 请注意“uwp”标签,它会显着改变可用的API。 - Alexei Levenkov
@AlexeiLevenkov 这样做可以吗?我觉得为正在运行的线程创建异步任务有点奇怪... - ThisHandleNotInUse
我会毫不犹豫地使用它,但存储应用程序不是我有任何合理经验的领域 - 所以无法说是否有更好的方法。通常,同步异步任务的开销(当任务在同一线程上同步完成时)相对较低。我唯一要做的就是尽可能将所有更新捆绑到单个调用中。 - Alexei Levenkov
在我看来,总是调用RunAsync()是可以的。坦白地说,在我看来,最好设计代码,以便仅从适当的线程更新属性。通常很容易保持在UI线程上,除了后台操作,将更新推回到UI线程。但如果你发现自己处于无法工作的情况下,只需调用RunAsync()或类似方法即可。请参见我相关的抱怨:http://blogs.msmvps.com/duniho/2008/09/12/msdn-s-canonical-technique-for-using-control-invoke-is-lame/ - Peter Duniho
显示剩余3条评论
2个回答

22

5
需要注意的是,在 UWP 应用程序中,UI 线程并不是主线程。可以通过调试器轻松检查。例如,在页面的 Loaded 事件处理程序中设置断点,会显示 Dispatcher.HasThreadAccess == true,并且当前线程为“工作线程”,其“名称”为空,而“托管 ID”为 3。 - user4698855
6
CoreDispatcher可以通过CoreWindow.GetForCurrentThread().Dispatcher进行访问。花了我一点时间才找到 :P - Felix

2

我的儿子最近遇到了这个问题,所以我想添加一个更新的答案。

可以使用Core Dispatcher CoreWindow.GetForCurrentThread().DispatcherWindows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher 来访问主UI线程。

下面是一个实现Core Dispatcher并测试调用线程是否为主UI线程的类。如果是,则调用该操作,否则调用Dispatcher.RunAsync在主UI线程上执行它。

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); };
        }
    }

上述的类可如下使用:

// 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);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接