繁体   English   中英

在UI线程上创建和启动任务

[英]Creating and starting a task on the UI thread

当在工作线程上调用的方法需要在UI线程上运行代码并在执行其他操作之前等待它完成时,可以这样做:

    public int RunOnUi(Func<int> f)
    {
        int res = Application.Current.Dispatcher.Invoke(f);

        return res;
    }

但是,如果我想用任务做什么呢? 有没有办法让RunOnUi方法创建一个在UI上启动并返回它的任务,以便调用者(在工作线程上运行)可以等待它? 适合以下签名的东西: public Task<int> StartOnUi(Func<int> f)

一种方法如下:

public Task<int> RunOnUi(Func<int> f)
{
    var task = new Task<int>(f);
    task.Start(_scheduler);

    return task;
}

这里假设_schduler持有ui TaskScheduler 但是我不太习惯于创建“冷”任务并使用start方法来运行它们。 这是“推荐”的方式还是有更优雅的方式来做到这一点?

只需使用InvokeAsync而不是Invoke然后返回函数返回的DispatcherOperation<int>Task<int>

//Coding conventions say async functions should end with the word Async.
public Task<int> RunOnUiAsync(Func<int> f)
{
    var dispatcherOperation = Application.Current.Dispatcher.InvokeAsync(f);
    return dispatcherOperation.Task;
}

如果您无法访问.NET 4.5,则会更复杂一些。 您将需要使用BeginInvokeTaskCompletionSource来包装BeginInvoke返回的DispaterOperation

    public Task<int> RunOnUi(Func<int> f)
    {
        var operation = Application.Current.Dispatcher.BeginInvoke(f);
        var tcs = new TaskCompletionSource<int>();
        operation.Aborted += (sender, args) => tcs.TrySetException(new SomeExecptionHere());
        operation.Completed += (sender, args) => tcs.TrySetResult((int)operation.Result);

        //The operation may have already finished and this check accounts for 
        //the race condition where neither of the events will ever be called
        //because the events where raised before you subscribed.
        var status = operation.Status;
        if (status == DispatcherOperationStatus.Completed)
        {
            tcs.TrySetResult((int)operation.Result);
        }
        else if (status == DispatcherOperationStatus.Aborted)
        {
            tcs.TrySetException(new SomeExecptionHere());
        }

        return tcs.Task;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM