1

此 MSDN 页面有以下示例: 目的是包装无法在各种Func<T1, T2, T3>重载中表示的 APM 样式任务。

static Task<String> ReturnTaskFromAsyncResult()
{
    IAsyncResult ar = DoSomethingAsynchronously();     // <-- If this is an APM method, it's a bad example since most APM methods have a parameter for callback and state.
    Task<String> t = Task<string>.Factory.FromAsync(ar, _ =>
        {
            return (string)ar.AsyncState;
        });

    return t;
}

我的问题与功能有关DoSomethingAsynchronously();。我见过的大多数 APM 函数都需要参数回调和状态,这在本示例中是缺失的。

问题: “DoSomethingAsynchronously”中的回调和状态参数会发生什么变化

我需要做什么才能正确调用类似的函数?就我而言,我正在尝试像这样包装 Azure Table 调用

    Task CreateAsync(CloudTable tbl, CancellationToken token, object state)
    {
        ICancellableAsyncResult result = tbl.BeginCreate(null, state);  // Incorrect
        token.Register((o) => result.Cancel(), state);

        Task<bool> t = Task.Factory.FromAsync(result, _ =>
        {
            return (bool)result.AsyncState;
        });

        return t;
    }
    Task<bool> ExistsAsync(CloudTable tbl, CancellationToken token, object state)
    {
        ICancellableAsyncResult result = tbl.BeginExists(null, state);  // Incorrect
        token.Register((o) => result.Cancel(), state);

        Task<bool>  t = Task.Factory.FromAsync(result, _ =>
        {
            return (bool)result.AsyncState;
        });

        return t;
    }
4

1 回答 1

8

我认为您误解了state参数的用途。它就在那里:当在其中传递一个对象时,您可以通过访问来检索它AsyncState。(和类似stateCancellationToken.Register()。)在这种情况下,你不需要state任何东西,所以你应该null在那里通过。这也意味着您创建的方法没有理由具有state参数。

callback参数用于异步操作完成时要执行的代码。你需要的重载FromAsync()不使用这个,所以你也应该null在那里传递。

endMethod您似乎也对在委托中放入什么感到困惑。顾名思义,您应该EndXxx()在其中调用该方法(在您的情况下是EndCreate()and EndExists())。如果整个操作返回一些东西,它实际上会被 end 方法返回,所以你应该从委托中返回它。然后它将作为创建的结果可用Task。您还可以在委托中执行一些清理。就您而言,我认为在那里处理取消注册是有意义的,因为不再需要它。

因此,您的代码应类似于:

Task CreateAsync(CloudTable tbl, CancellationToken token)
{
    ICancellableAsyncResult result = tbl.BeginCreate(null, null);
    var cancellationRegistration = token.Register(result.Cancel);

    return Task.Factory.FromAsync(result, ar =>
    {
        cancellationRegistration.Dispose();
        tbl.EndCreate(ar);
    });
}

Task<bool> ExistsAsync(CloudTable tbl, CancellationToken token)
{
    ICancellableAsyncResult result = tbl.BeginExists(null, null);
    var cancellationRegistration = token.Register(result.Cancel);

    return Task.Factory.FromAsync(result, ar =>
    {
        cancellationRegistration.Dispose();
        return tbl.EndExists(ar);
    });
}

有关此主题的更多信息,请查看 Stephen Toub 的任务和 APM 模式

于 2012-11-17T13:01:16.070 回答