【问题标题】:c# synch and asynch calls on blob upload and wait functionc# 对 blob 上传和等待函数的同步和异步调用
【发布时间】:2019-12-25 03:31:49
【问题描述】:

我试图了解这些代码行之间的区别。我有一个名为 arContents 的内存流对象,当它的大小很小时可以正常工作。我看到文件上传了。

blockBlob.UploadFromStreamAsync(arContents)

但是当内存流很大时,上面的代码运行没有错误但没有上传文件。但是,当我添加了 WAIT() 函数调用时,它起作用了。

blockBlob.UploadFromStreamAsync(arContents).Wait();

我想首先了解什么是等待调用以及为什么它是异步调用。猜猜也想知道异步调用和同步调用的区别。

另外,我也看到了 await .. 像这样的代码

await blockBlob.UploadFromStreamAsync(arContents)

有什么区别?

谢谢

【问题讨论】:

标签: c# multithreading async-await azure-blob-storage


【解决方案1】:

我看到你在你的问题上标记了multithreading,所以我认为重要的是要注意异步和多线程是两个完全不同的东西。通读 Microsoft 的文章 The Task asynchronous programming model in C#,了解它们的不同之处。关于烹饪的例子确实有助于阐明这一点。

当您调用异步方法时,任务(无论是什么)都会启动。但您通常也希望:

  1. 知道它已成功完成,或者
  2. 使用任务返回的结果(例如,如果它正在检索数据)

当事情变得有趣时,您如何以及何时这样做。异步编程的重点是允许线程在等待其他事情发生(网络请求、来自硬盘驱动器的数据等)的同时执行其他操作,而不是让线程闲置直到任务完成。

您可能已经体验过一些完全锁定的程序,并且在它执行某些操作时不允许您执行任何操作。这就是异步编程可以避免的。

在您的第一个示例中,您根本不需要等待结果。这通常被称为“一劳永逸”。您启动任务,然后代码执行立即移至下一行,您将永远不知道任务是否成功完成。

使用.Wait() 根本不是异步的。它将锁定线程,直到任务完成。更糟糕的是,当您尝试强制异步方法同步时,有时会导致应用程序无法恢复的死锁。搜索c# async wait deadlock,你会发现很多例子和解释。

理想情况下,您需要使用await。当你使用它时会发生这种情况:

  1. 方法 (UploadFromStreamAsync) 被调用。
  2. 当异步操作开始时,UploadFromStreamAsync 返回一个Task
  3. await 关键字将查看Task,如果它不完整,它将把当前方法的其余部分放在“待办事项”列表中,以供Task 完成并返回一个为调用方法添加新的Task

只要您在调用堆栈中一直使用async,那么此时,线程就可以开始执行其“待办事项”列表中的其他事情。在 ASP.NET 中,它可能正在处理传入的新请求。在桌面应用程序中,它可能正在响应用户输入。这会发生在同一个线程上

只要该任务完成,await 就会从 Task 中提取返回值。如果该方法只返回一个Task,那么这类似于void(没有返回值)。如果是Task<T>,则返回T类型的对象。然后您的代码在await 行之后恢复执行。

这听起来很复杂,但您真的不需要完全了解它在做什么,这是设计使然。 C# 的这一特性使您能够以与普通同步编程非常相似的方式使用异步编程。例如:

public async Task Upload() {
     ...
    await blockBlob.UploadFromStreamAsync(arContents);
}

将与此完全相同:

public void Upload() {
     ...
    blockBlob.UploadFromStream(arContents);
}

它们看起来非常相似,只是使用 async/await 会给您带来我上面提到的好处,而第二个则不会。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-17
    • 2020-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    相关资源
    最近更新 更多