UWP C# Return UI 对象到主线程上的同步扩展方法

UWP C# Return UI object to synchronous extension method on main thread

我正在尝试为 Page class 编写一个扩展方法,它将 return 一个用户控件,它是根 Grid 的动态创建的子控件。我遇到的问题是使用 Page class.

Content 属性

目的是为了return控件检查控件的属性,并且主要从主线程调用。

这是我正在尝试做的事情:

public static MyUserControl GetControlByTag(this Page page, int tag) {
    //throws "marshalled from a different thread" exception
    Grid rootGrid = page.Content as Grid;  

    if(rootGrid != null) {
        var controls = rootGrid.Children.OfType<MyUserControl>();

        foreach(MyUserControl control in controls)
        {
            if(control.Tag == tag) return control;
        }

    return null;
}

我已经尝试制作 return 类型 Task<Grid> 的辅助方法来获取对象,但我找不到同步 return 异步任务的方法,我似乎无法找到同步 return 来自 page.Dispatcher.RunAsync().

的值的方法

这通常是 XAML 布局的样子:

<Page>
    <Grid>
        ...
        ...
        ...
        <MyUserControl/>
        <MyUserControl/>
        <MyUserControl/>
    <Grid/>
</Page>

我通过 MSDN 找到了解决方案:

public static MyUserControl GetControlByTag(this Page page, int tag) {
    MyUserControl rtn = null; 

    page.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
        Grid rootGrid = page.Content as Grid;

        if(rootGrid != null) {
            var controls = rootGrid.Children.OfType<MyUserControl>();

            foreach(MyUserControl control in controls)
            {
                if(control.Tag == tag) rtn = control;
            }
        }
    }).AsTask().Wait(); //Runs the dispatcher synchronously

    return rtn;
}

参考资料post: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/e15d4852-a601-4bd6-88b4-42480fd71e70/win-rt-awaiting-the-dispatcherrunasync?forum=winappswithcsharp

编辑:但是请注意,如果要在整个应用程序中使用它:您可能必须检查该方法是否已经具有线程访问权限。到目前为止,我还没有找到一种优雅的方式来做到这一点,但它的基础是这样的:

public static MyUserControl GetControlByTag(this Page page, int tag) {
    Grid rootGrid = page.Content as Grid;

    if(page.Dispatcher.HasThreadAccess) {
        //Code to run
    }
    else {
        page.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
            //Code to run
        }).AsTask().Wait();
    }
}