【发布时间】:2012-05-21 16:24:06
【问题描述】:
如何在 WinRT (Windows 8 Metro) 的 UI 线程上运行代码?
Invoke 方法不存在。
【问题讨论】:
-
未来读者请注意:请记住,如果您的应用有多个窗口 - 会有多个 UI 线程和调度程序。
标签: .net multithreading windows-8 windows-runtime dispatcher
如何在 WinRT (Windows 8 Metro) 的 UI 线程上运行代码?
Invoke 方法不存在。
【问题讨论】:
标签: .net multithreading windows-8 windows-runtime dispatcher
直接从非UI线程获取CoreWindow更容易。以下代码适用于任何地方,即使 GetForCurrentThread() 或 Window.Current 返回 null。
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
<lambda for your code which should run on the UI thread>);
例如:
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
});
您需要引用 Windows.ApplicationModel.Core 命名空间:
using Windows.ApplicationModel.Core;
【讨论】:
CoreApplication.MainView.CoreWindow.Dispatcher 不适合你?尝试其他解决方案时是否有异常? Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher? this.Dispatcher?
Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher,但这也引发了异常。我猜this.Dispatcher不适用于Windows.Runtime。我已经将它作为单独的question发布。
用途:
从你的 UI 线程,执行:
var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
来自您的背景(非 UI 线程)
dispatcher.RunAsync(DispatcherPriority.Normal,
<lambda for your code which should run on the UI thread>);
这应该适用于 CP 和更高版本。
【讨论】:
CoreApplication.MainView.CoreWindow.Dispatcher
用途:
this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Frame.Navigate(typeof(Welcome), this));
它对我有用。
【讨论】:
在我看来这是一种更简单的方法。
获取与 UI 关联的 TaskScheduler。
var UISyncContext = TaskScheduler.FromCurrentSynchronizationContext();
然后在上面的UISyncContext上启动一个新Task。
Task.Factory.StartNew(() => { /* Do your UI stuff here; */}, new System.Threading.CancellationToken(), TaskCreationOptions.PreferFairness, UISyncContext);
【讨论】:
DispatcherTimer 也是一个选项。
我将它用于必须在 Xaml-designer 中运行的代码(CoreWindow.Dispatcher,...在 UWP-designer 中不可用)
var localTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(0)
};
localTimer.Tick += (timer, e) =>
{
(timer as DispatcherTimer).Stop();
action();
};
localTimer.Start();
免责声明:
我应该注意,如果其他所有方法都失败了,这应该是最后的选择。
【讨论】:
在 UWP 上,我在尝试设置 CaptureElement 控件(在 XAML 中定义)的 Source 属性时遇到问题,它抱怨在不同的线程准备,即使我试图从被调用的代码中设置它通过 Page_Loaded 事件处理程序。我最终使用它来解决它:
previewControl.Dispatcher.TryRunAsync(CoreDispatcherPriority.Normal, () => {
previewControl.Source = _mediaCapture;
}).GetAwaiter().GetResult();
【讨论】: