【问题标题】:Async upload to Azure isn't blocking even though calling Task.WaitAll(task)即使调用 Task.WaitAll(task),异步上传到 Azure 也不会阻塞
【发布时间】:2025-12-06 18:25:01
【问题描述】:

我正在将文件上传到 Azure。代码可以正常上传文件,但我的页面在完成之前刷新并显示旧图像。我可以手动刷新页面并显示新图像。为什么我的方法没有等待任务完成?

    public static bool Upload(Stream image, String id)
    {
        try {
            var key = String.Format("{0}.png", id);

            image.Position = 0;

            var container = new CloudBlobContainer(new Uri(string.Format("{0}/{1}", Host, Container)), Credentials);

            var blob = container.GetBlockBlobReference(key);

            blob.Properties.ContentType = "image/png";

            Task task = Task.Run(() => { blob.UploadFromStreamAsync(image); });

            Task.WaitAll(task);
        }
        catch {
            return false;
        }

        return true;
    }

回答:非常感谢 aleksey.berezan。结果证明甚至没有使用该任务。

所以这个:

Task task = Task.Run(() => { blob.UploadFromStreamAsync(image); });

Task.WaitAll(task);

变成了这样:

Task.WaitAll(blob.UploadFromStreamAsync(image));

一切都很完美!

【问题讨论】:

  • offtop: catch { return false; } - 在家里试试这个,但不要在工作中
  • 如何调用Upload 方法?能否请您发布您的网页代码?
  • 是的,捕获的东西是速记。我还没有完全实现错误处理。并且调用只是一个基本的静态调用。 DataStorageUtility.Upload(data.Image.InputStream, id);
  • 如果你直接调用Task而不是blob.UploadFromStreamAsync(image);,它会起作用吗?
  • 感谢 aleksey.berezan!这很完美。写下这个作为答案,我会标记它为你回答。

标签: c# azure asynchronous blob task


【解决方案1】:

这个人:

blob.UploadFromStreamAsync(image);

开始新任务。
所以这个人:

Task.Run(() => { blob.UploadFromStreamAsync(image); });

刚刚启动任务启动任务。这样这段代码:

Task task = Task.Run(() => { blob.UploadFromStreamAsync(image); });

Task.WaitAll(task);

只会等到上传任务被触发(这会立即发生),而不是等待上传任务完成。

要解决这种情况,您必须编写:

Task.WaitAll(blob.UploadFromStreamAsync(image));

【讨论】:

  • 只是一个问题:如果调用Task.WaitAll(blob.UploadFromStreamAsync(stream)) 与同步调用blob.UploadFromStream(stream) 相比,实际上有什么区别吗?我的意思是因为我们在当前线程中等待另一个线程完成......所以当前线程没有被释放到线程池,因为这段代码中没有异步/等待......所以基本上正如我所看到的那样,两个调用都是相同。
  • 在我的机器上(win8/net45/x64)这个家伙blob.UploadFromStream(image);在当前线程中运行,但是这个Task.WaitAll(blob.UploadFromStreamAsync(image));在不同的线程中运行操作并在当前等待完成。因此,在这两种情况下,当前线程都处于忙碌状态,直到操作完成,但在第二种情况下,实际操作涉及到一个额外的线程。
  • 从你所说的,我可以推断UploadFromStream 速度更快,使用的资源更少。在这两种情况下,因为它不必创建新线程。
【解决方案2】:

您正在等待以Task.Run 开始的任务。你想等待UploadFromStreamAsync。事实上,我不明白你为什么需要Task.Run。它只会让事情变得更慢。您将工作转移到线程池,然后等待它完成。

只要有同步版本的UploadFromStreamAsync 就可以了。或者,在UploadFromStreamAsync 返回的任务上调用Wait(不太可取)。

您可能想要修改您的异常处理。您永远不会发现此方法中的错误,因为所有异常都会被丢弃。

【讨论】:

  • 异常处理只是临时处理。我还没有完全实现这个方法。只是调用 UploadFromStreamAsync 也不起作用。但调用 Task.WaitAll(UploadFromStreamAsync) 最终工作。
  • 你最好直接调用同步版本。如果这不可能,请在任务上调用Wait 而不是Task.WaitAll,这不必要地复杂。
最近更新 更多