gpt4 book ai didi

c# - 正在清除异步问题并等待吗?

转载 作者:太空宇宙 更新时间:2023-11-03 17:19:43 25 4
gpt4 key购买 nike

我最近一直在学习异步编程,我想我已经掌握了它。异步编程很简单,只需允许我们的程序执行多任务即可。

编程的awaitasync带来了困惑,似乎让我更加困惑了,有人可以帮我解答一些问题吗?

我看不到async关键字,只是您对某个方法不满意而使Visual Studio知道该方法可能await某些内容,并且允许您警告您。如果它还有其他实际上会影响某事的特殊含义,那么有人可以解释吗?

转到await,在与一位朋友交谈后,我被告知我有1大错误,await不会阻塞当前方法,它只是执行该方法中剩下的代码,并在自己的时间内进行异步操作。

现在,我不确定这种情况发生的频率,但是可以说您有一些类似的代码。

Console.WriteLine("Started checking a players data.");

var player = await GetPlayerAsync();

foreach (var uPlayer in Players.Values) {
uPlayer.SendMessage("Checking another players data");
}

if (player.Username == "SomeUsername") {
ExecuteSomeOperation();
}

Console.WriteLine("Finished checking a players data.");


如您所见,我在 GetPlayerAsync上运行了一些异步代码,如果我们深入了解范围并且需要访问播放器,但是还没有返回播放器,会发生什么呢?

如果它不阻塞方法,它怎么知道玩家不为空,是否做了一些魔术,然后等我们遇到这种情况,还是只是禁止自己以这种方式编写方法并处理它我们自己。

最佳答案

我最近一直在学习异步编程,我想我已经掌握了它。


我是该功能的设计师之一,我甚至感觉自己还差一点就不熟悉它,而您在问初学者级别的问题,并且有一些非常非常错误的想法,所以这里有些狂妄自大。疑似。


  异步编程只是让我们的程序执行多任务。


假设您问“为什么有些物质硬而有些软?”我回答“物质是由原子排列构成的,有些原子排列是硬的,有些是软的”。尽管这无疑是正确的,但我希望您能避免这种无用的解释。

同样,您刚刚用另一个模糊的单词“ multitask”替换了模糊的单词“ asynchronous”。这是一个解释,什么也解释不了,因为您尚未明确定义多任务的含义。

异步工作流程无疑是关于执行多个任务的。这就是工作流中基本工作单元是Task<T> monad的原因。异步工作流程是通过在多个任务之间建立依赖关系图来组成多个任务的。但这并不能说明软件中如何真正实现该工作流程。这是一个复杂而深刻的主题。


  我看不到async关键字太多,只是您对某个方法不满意而使Visual Studio知道该方法可能正在等待某种东西,并且允许您警告它。


基本上是正确的,尽管不要认为它告诉Visual Studio。 VS不在乎。您正在讲的是C#编译器。


  如果它还有其他实际上会影响某事的特殊含义,那么有人可以解释吗?


它只是使await成为方法内的关键字,并对返回类型进行限制,并将return的含义更改为“信号表明与此调用关联的任务已完成”,以及其他一些内部管理细节。


  等待不会阻止当前方法


当然可以。您为什么会认为不是呢?

它不会阻塞线程,但是肯定会阻塞方法。


  它只是执行该方法中剩下的代码,并在自己的时间内执行异步操作。


绝对不。这是完全落后的。 await与此相反。 “等待”表示如果任务未完成,则返回到调用方,并注册此方法的其余部分作为任务的继续。


  如您所见,我在GetPlayerAsync上运行了一些异步代码,如果我们深入了解范围并且需要访问播放器,但还没有返回播放器,会发生什么呢?


那永远不会发生。

如果在执行player时分配给await的值不可用,则等待返回,并且当该值可用时(或任务异常完成时),将恢复方法的其余部分。

请记住,await表示异步等待,这就是为什么我们将其称为“ await”。等待是异步工作流程中的一点,在该流程中,待完成的任务完成之前,工作流程无法继续进行。这与您描述等待的方式相反。

同样,请记住异步工作流是什么:它是任务的集合,其中这些任务相互依赖。我们通过在依赖点放置await表示一个任务对另一任务的完成有依赖。

让我们更详细地了解您的工作流程:

var player = await GetPlayerAsync();
foreach (var uPlayer in Players.Values) ...
if (player.Username == "SomeUsername") ...


等待意味着“该工作流程的其余部分将无法继续,直到获得播放器为止”。这是真的吗?如果您希望在提取播放器之前不执行 foreach,那么这是正确的。但是foreach不依赖于播放器,因此我们可以这样重写:

Task<Player> playerTask = GetPlayerAsync();
foreach (var uPlayer in Players.Values) ...
Player player = await playerTask;
if (player.Username == "SomeUsername") ...


瞧,我们已经将依赖点移到了工作流程的后面。我们启动“获取玩家”任务,然后进行foreach,然后在需要之前检查玩家是否可用。

如果您相信 await以某种方式“接听电话并使它异步”,则应该消除这种信念。 await接受任务,如果未完成,则返回。如果完成,则提取该任务的值并继续。 “获取播放器”操作已经是异步的, await并非如此。


  如果不阻塞该方法,它将如何得知玩家不为空


它确实阻止了该方法,或更准确地说,它挂起了该方法。

该方法将挂起,直到任务完成并提取值后才恢复。

它不会阻塞线程。它返回,以便呼叫者可以继续在其他工作流程中进行工作。任务完成后,继续将安排在当前上下文上,该方法将恢复。

关于c# - 正在清除异步问题并等待吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49306357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com