【问题标题】:C# 5 async / await simplistic explanation [duplicate]C# 5 async / await 简单解释 [重复]
【发布时间】:2013-01-12 02:47:22
【问题描述】:

可能重复:
Brief explanation of Async/Await in .Net 4.5

我用 C# 编程已经有一段时间了,但我无法理解新的 async / await 语言功能是如何工作的。 p>

我写了一个这样的函数:

public async Task<SocketError> ConnectAsync() {
    if (tcpClient == null) CreateTCPClient();
    if (tcpClient.Connected)
        throw new InvalidOperationException("Can not connect client: IRCConnection already established!");

    try {
        Task connectionResult = tcpClient.ConnectAsync(Config.Hostname, Config.Port);
        await connectionResult;
    }
    catch (SocketException ex) {
        return ex.SocketErrorCode;
    }

    return SocketError.Success;
}

但显然,这没有意义,对吧?因为我在等待TcpClient.ConnectAsync的结果之后就马上上线了。

但我想编写我的 ConnectAsync() 函数,以便它本身可以在另一种方法中等待。这是正确的方法吗?我有点失落。 :)

【问题讨论】:

  • 如果你想要一个只有成功/失败(没有“结果”值)的async方法,那么返回Task而不是Task&lt;SocketError&gt;。返回错误代码不是 .NET 中的正常做法。
  • Stephen:我实际上想返回 SocketError(如果有),或者 SocketError.Success 如果没有。但是,您是说让任何 SocketException 传播给调用者会更好吗?
  • @Motig 是的,他就是这么说的。
  • 本系列文章可能对您有所帮助。从底部开始;它们按时间倒序排列。 blogs.msdn.com/b/ericlippert/archive/tags/async

标签: c# .net async-await


【解决方案1】:

我希望您已经遇到过 yield return 语法来创建迭代器。它暂停执行,然后在需要下一个元素时继续执行。你可以想到await 来做一些非常相似的事情。等待异步结果,然后该方法的其余部分继续。当然,它不会阻塞,因为它正在等待。

【讨论】:

  • 是的,我有。按照我的理解,yield return 只会根据需要返回集合中的元素。那么你是说 tcpClient.ConnectAsync() 方法不会阻塞,直到从程序的另一个区域访问 tcpClient 上的某些字段?
  • @Motig - 在这种情况下,直到异步操作的结果可用。
【解决方案2】:

看起来不错,但我相信这是语法:

await tcpClient.ConnectAsync(Config.Hostname, Config.Port);

因为 await 适用于“任务”返回,所以除非函数有任务结果,否则不会返回。

这是来自microsoft的非常清楚的例子

private async void button1_Click(object sender, EventArgs e)
{
    // Call the method that runs asynchronously.
    string result = await WaitAsynchronouslyAsync();

    // Call the method that runs synchronously.
    //string result = await WaitSynchronously ();

    // Display the result.
    textBox1.Text += result;
}

// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window 
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}

// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
    // Add a using directive for System.Threading.
    Thread.Sleep(10000);
    return "Finished";
}

【讨论】:

    【解决方案3】:

    类似这样的:

    • tcpClient.ConnectAsync(Config.Hostname, Config.Port) 将异步运行;
    • await connectionResult 之后执行将返回给ConnectAsync 方法的调用者;
    • 然后await connectionResult 将完成它的异步工作,你的方法的其余部分将被执行(如回调);

    此功能的祖先:

    Simplified APM with the AsyncEnumerator

    More AsyncEnumerator Features

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-13
      • 1970-01-01
      • 2019-03-04
      相关资源
      最近更新 更多