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

2023-09-02 02:09:28 作者:浪不出來的漫

在.NET中,Windows 8和Windows Phone 7我有code与此类似:

In .NET, Windows 8 and Windows Phone 7 I have code similar to this:

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

我怎么会做一些便携式类库?这将是不错的一个平台无关的实现了这一点。我的想法是利用第三方物流是不具备的WP7,但肯定会很快。

How would I do something in the portable class library? It would be nice to have one platform agnostic implementation of this. My idea is to use the TPL which is not available in WP7 but definitely will be soon.

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

我不能确定的唯一的事情就是这样的业绩影响将。也许我会做一些测试。

The only thing I'm unsure about is what the performance implications of this would be. Perhaps I'll do some tests.

推荐答案

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

With the advent of the TPL. I came up with a slightly improved version of the accepted answer which returns a task and can be await'ed using the new async and await keywords.

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