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」のコールバックと状態のパラメーターはどうなりますか

これに似た関数を適切に呼び出すにはどうすればよいですか?私の場合、AzureTableの呼び出しを次のようにラップしようとしています

    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()andEndExists()です)。操作全体が何かを返す場合、それは実際には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);
    });
}

このトピックの詳細については、 StephenToubのタスクとAPMパターンを参照してください。

于 2012-11-17T13:01:16.070 に答える