将ICloudBlob.UploadFromStream转换为Task.Factory.FromAsync(begin,end,params)

时间:2013-04-21 16:53:26

标签: azure asynchronous blob

我想转换:

blob.UploadFromStream(stream, null, new BlobRequestOptions { RetryPolicy = new LinearRetry(TimeSpan.FromMilliseconds(100), 3) });

                Task uploadStreamTask = Task.Factory.FromAsync(
                    blob.BeginUploadFromStream,
                    blob.EndUploadFromStream,
                    stream,
                    null);

我的问题是,如果仅传递给beginUploadFromStream的流参数,则上述工作正常。我无法弄清楚如何让它接受其他参数,如我的第一个例子。

1 个答案:

答案 0 :(得分:1)

您的代码尝试调用不带任何参数的BeginUploadFromStream-Method的重载 - 但没有这样的重载。为了从需要参数的异步方法创建任务 - 异步模式,请使用FromAsync<>-Method的通用版本。您可以指定Begin-Method需要的参数。

对于Begin / EndUploadFromStream方法,代码如下所示:

Task.Factory.FromAsync<Stream>(blob.BeginUploadFromStream, blob.EndUploadFromStream, stream, null);

但是,既然你需要传递 BlobRequestOptions ,事情也会变得复杂一些:

接受BlobRequestOptions参数的BeginUploadFromStream-Method的重载总共需要四个参数。但是FromAsync&lt;&gt;没有过载。接受begin方法的三个以上输入参数的方法。

这就是你可以使用FromAsync&lt;&gt;方法虽然:

  1. 为ICloudBlob.BeginUploadFromStream创建一个扩展方法,该方法需要两个参数(流和BlobRequestOptions)并将它们正确传递给原始的Begin-Method

    public static class Extensions
    {
        public static IAsyncResult BeginUploadFromStream(this ICloudBlob blob, Stream source, BlobRequestOptions options, AsyncCallback callback, object state)
        {
            return blob.BeginUploadFromStream(source, 
                                              null, 
                                              options, 
                                              null, 
                                              callback, 
                                              state);
        }
    }
    
  2. 使用Async重载来创建任务

    Task.Factory
        .FromAsync<Stream, BlobRequestOptions>(blob.BeginUploadFromStream,
                                               blob.EndUploadFromStream, 
                                               stream,
                                               options, 
                                               null);
    
  3. 如果您需要将所有四个参数传递给BeginUploadFromStream-Method,请告诉我。我也知道如何解决这个问题。

    <强>更新 这是一个四参数Begin方法的解决方案。我期望这个想法能够产生更通用的东西,并且使用更少的反射,但是现在它只适用于没有返回值的EndMethod。

    public static Task FromAsync<TArg1, TArg2, TArg3, TArg4>(this TaskFactory factory,
                                                             Func<TArg1, TArg2, TArg3, TArg4, AsyncCallback, object, IAsyncResult> beginMethod,
                                                             Action<IAsyncResult> endMethod,
                                                             TArg1 arg1,
                                                             TArg2 arg2,
                                                             TArg3 arg3,
                                                             TArg4 arg4,
                                                             object state,
                                                             TaskCreationOptions creationOptions)
        {
            // create a promise task that will wait until the async stuff is done
            var constructor = typeof(Task).GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, new Type[] { typeof(object), typeof(TaskCreationOptions), typeof(bool) }, null);
            var promise = constructor.Invoke(new object[] { state, creationOptions, true }) as Task;
    
            // perform the async pattern method
            try
            {
                IAsyncResult asyncResult = beginMethod(arg1, arg2, arg3, arg4, delegate(IAsyncResult iar)
                {
                    if (!iar.CompletedSynchronously)
                    {
                        // complete the async pattern
                        endMethod(iar);
                        var mFinish = typeof(Task).GetMethod("Finish", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                        mFinish.Invoke(promise, new object[] { true });
                    }
                }, state);
                if (asyncResult.CompletedSynchronously)
                {
                    // complete the async pattern synchronously
                    endMethod(asyncResult);
                    var mFinish = typeof(Task).GetMethod("Finish", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                    mFinish.Invoke(promise, new object[] { true });
                }
            }
            catch (Exception ex)
            {
            }
    
            return promise as Task;
        }