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

标签 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 的流参数,则上述方法有效。我不知道如何让它接受第一个示例中的其他参数。

最佳答案

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

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

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

但是由于您还需要传递BlobRequestOptions,所以事情变得有点复杂:

接受 BlobRequestOptions 参数的 BeginUploadFromStream-Method 的重载总共需要四个参数。但是 FromAsync<> 方法没有重载,该方法为 begin 方法接受三个以上的输入参数。

这就是如何使用 FromAsync<> 方法:

  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. 使用异步重载创建任务

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

如果您需要将所有四个参数传递给 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;
    }

关于azure - 将 ICloudBlob.UploadFromStream 转换为 Task.Factory.FromAsync(begin,end,params),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16133689/

相关文章:

Windows Azure 上的交易计费

.NET 4.5 中的 WCF/svcutil 默认生成不可用的代码

node.js - Azure node.js SDK 的 createContainerIfNotExist 方法身份验证失败

java - 通过 Hibernate(不是 JDBC)从 blob 中检索图像

php - Sendgrid Azure PHP

sql-server - Polybase CREATE EXTERNAL TABLE 跳过 header

javascript - 如何确保 Angular 服务构造函数中的异步初始化完成?

java - thenAccept 和 thenApply 的区别

angular - 如何在 Angular 中通过 HTTP 检索二进制数据?

azure - 获取 Powershell 错误无法引用 UpdateAzureRm-Vmss 上不同虚拟网络的子网