从WinRT中的线程更新UI

自从几天前发布了Windows 8消费者预览版以来,我正在使用C#开发新的WinRT(针对Metro应用程序),并且已经将我自己编写的IRC类移植到新的线程和网络中。

问题是:我的类正在运行一个线程,用于从服务器接收消息。 如果发生这种情况,该线程正在进行一些解析,然后触发事件以通知应用程序。 然后,订阅的function“应该”更新UI(文本块)。

这是问题,线程无法更新UI,并且似乎不再可能使用.NET 4.0的调用方法。 是否有更新的解决方法,甚至是更新UI的更好方法? 如果我尝试从事件订阅者更新UI,我将得到此Exception

该应用程序调用了一个为不同线程编组的接口(来自HRESULT的exception:0x8001010E(RPC_E_WRONG_THREAD))

在WinRT(以及一般的C#5)中处理此问题的首选方法是使用asyncawait

 private async void Button_Click(object sender, RoutedEventArgs e) { string text = await Task.Run(() => Compute()); this.TextBlock.Text = text; } 

这里, Compute()方法将在后台线程上运行,当它完成时,该方法的其余部分将在UI线程上执行。 与此同时,UI线程可以随心所欲地做任何事情(比如处理其他事件)。

但是,如果您不想或不能使用async ,您可以使用与WPF中类似(尽管不同)的方式使用Dispatcher

 private void Button_Click(object sender, RoutedEventArgs e) { Task.Run(() => Compute()); } private void Compute() { // perform computation here Dispatcher.Invoke(CoreDispatcherPriority.Normal, ShowText, this, resultString); } private void ShowText(object sender, InvokedHandlerArgs e) { this.TextBlock.Text = (string)e.Context; } 

我认为这是一种更简单的方法!

首先使用以下内容捕获UI SyncronizationContext:

  var UISyncContext = TaskScheduler.FromCurrentSynchronizationContext(); 

运行您需要的服务器调用操作或任何其他后台线程操作:

  Task serverTask= Task.Run(()=> { /* DoWorkHere(); */} ); 

然后在您在第一步中捕获的UISyncContext上执行UI操作:

  Task uiTask= serverTask.ContinueWith((t)=>{TextBlockName.Text="your value"; }, UISyncContext); 

IMO我认为“ThreadPool”是推荐的路线。

https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh465290.aspx

 public static Task InvokeBackground(Func action) { var tcs = new TaskCompletionSource(); var unused = ThreadPool.RunAsync(async (obj) => { await action(); tcs.TrySetResult(true); }); return tcs.Task; }