便携式类库相当于Dispatcher.Invoke或Dispatcher.RunAsync的(Por

2019-06-25 21:43发布

在.NET,Windows 8和Windows Phone 7的我有类似下面的代码:

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

我会怎么做便携式类库的东西吗? 这将是不错的一个平台无关的实现这一点。 我的想法是使用TPL这是不是在WP7可用,但肯定会很快。

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

我不能确定的唯一的事情就是这对性能的影响会是什么。 也许我会做一些测试。

Answer 1:

您可以使用SynchronizationContext.Post或发送方法。 它是便携式的,当你使用一个UI框架与调度员则当前同步上下文将工作委托给调度。

具体地说,可以使用下面的代码:

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


Answer 2:

随着第三方物流的出现。 我想出了接受的答案它返回一个任务,可以使用新的异步被await'ed和等待关键字略微改进版。

public Task RunAsync(Action action)
{
    TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>();

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


文章来源: Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync