可移植类库,相当于Dispatcher.Invoke或Dispatcher.RunAsync

在.NET,Windows 8和Windows Phone 7中,我的代码与此类似:

public static void InvokeIfRequired(this Dispatcher dispatcher, Action action) { if (dispatcher.CheckAccess()) { action(); } else { dispatcher.Invoke(action); } } 

我如何在便携式类库中做一些事情? 有一个平台无关的实现这将是很好的。 我的想法是使用WP7中没有的TPL,但肯定会很快。

 // PortableDispatcher must be created on the UI thread and then made accessible // maybe as a property in my ViewModel base class. public class PortableDispatcher { private TaskScheduler taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); public void Invoke(Action action) { if (Alread on UI thread. How would I do this.) { action(); } Task.Factory.StartNew( action, CancellationToken.None, TaskCreationOptions.None, taskScheduler); } } 

我唯一不确定的是它的性能影响。 也许我会做一些测试。

您可以使用SynchronizationContext.Post或Send方法。 它是可移植的,当您将UI框架与调度程序一起使用时,当前的同步上下文会将工作委派给Dispatcher。

具体来说,您可以使用以下代码:

 void InvokeIfRequired(this SynchroniationContext context, Action action) { if (SynchroniationContext.Current == context) { action(); } else { context.Send(action) // send = synchronously // context.Post(action) - post is asynchronous. } } 

随着TPL的出现。 我想出了一个稍微改进的接受答案的版本,它返回一个任务,可以使用新的async和await关键字等待。

 public Task RunAsync(Action action) { TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); if (this.synchronizationContext == SynchronizationContext.Current) { try { action(); taskCompletionSource.SetResult(null); } catch (Exception exception) { taskCompletionSource.SetException(exception); } } else { // Run the action asyncronously. The Send method can be used to run syncronously. this.synchronizationContext.Post( (obj) => { try { action(); taskCompletionSource.SetResult(null); } catch (Exception exception) { taskCompletionSource.SetException(exception); } }, null); } return taskCompletionSource.Task; }