【问题标题】:async await for a simple wrapper method异步等待一个简单的包装方法
【发布时间】:2015-03-26 04:05:19
【问题描述】:

如果我编写的方法只是包装异步方法,例如:

public async Task WrapMethodAsync()
{
    using(var smtpClient = new SmtpClient())
    {
        await smtpClient.SendMailAysnc(new MailMessage());
    }
}

是不是和下面的一样:

public Task WrapMethodAsync()
{
    using(var smtpClient = new SmtpClient())
    {
        return smtpClient.SendMailAysnc(new MailMessage());
    }
}

或者后者实际上不是异步运行的?

【问题讨论】:

  • 我确定这是重复的。答案是“大部分”——不同之处在于如果SmtpClient 构造函数(或MailMessage 构造函数,或SendMailAsync 方法的开始)抛出异常,在第一种情况下,您将得到一个错误的任务;在第二种情况下,您将立即获得异常。
  • 这可能是重复的,但对于我来说,我不知道要搜索什么。
  • 明白。希望其他人能找到。
  • 搜索“C# await 教程”。这是非常基本的,你必须能够自己回答这个问题。如果你不知道这个问题的答案,使用异步编程是相当危险的。
  • @JonSkeet 处理客户端的语义远比异常处理语义重要。

标签: c# .net asynchronous async-await task-parallel-library


【解决方案1】:

在这个确切的场景中,由于using 范围,这两种情况截然不同

在第一种情况下,您在处理客户端之前(异步)等待SendMailAysnc 操作完成,而在另一种情况下,您不需要,因此您将在操作仍在运行时处理客户端

在一般行为没有差异的一般情况下。例如:

public async Task Run()
{
    throw new Exception("stored");
    await Task.Delay(-1);
}

VS 这个:

public Task Run()
{
    throw new Exception("thrown");
    return Task.Delay(-1);
}

区别在于async方法对整个async机制(包括状态机)有轻微开销,而非async任务返回方法有不同异常语义,因为异常直接抛出而不存储在返回的任务中

【讨论】:

    【解决方案2】:

    第一个 sn-p 在发送邮件后处理客户端,后者在它开始发送邮件之后处理客户端,但在它完成之前。假设客户端在发送消息时不应该被释放,这意味着第一个解决方案是非常有问题的。

    另外,错误处理语义不同;在第一个 sn-p 中构造 Task 的异常将导致方法抛出异常,而在第二个 sn-p 中它们会导致返回任务被标记为 Faulted 并设置了适当的异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      相关资源
      最近更新 更多