对于任何在Unity中研究这个困难主题的人来说都是非常重要的,
请务必看到我提出的另一个问题,它提出了相关的关键问题:
具体来说,在统一中,“等待”字面上会返回到哪里?
对于C#专家,Unity是单线程的sup1/sup>
在另一个线程上进行计算是很常见的。
当你在另一个线程上做某事时,你经常使用async/wait,因为,嗯,所有优秀的C#程序员都说,这是做这件事的简单方法!
void TankExplodes() {
ShowExplosion(); .. ordinary Unity thread
SoundEffects(); .. ordinary Unity thread
SendExplosionInfo(); .. it goes to another thread. let's use 'async/wait'
}
using System.Net.WebSockets;
async void SendExplosionInfo() {
cws = new ClientWebSocket();
try {
await cws.ConnectAsync(u, CancellationToken.None);
...
Scene.NewsFromServer("done!"); // class function to go back to main tread
}
catch (Exception e) { ... }
}
好的,当你这样做的时候,当你在unity/c#中以更常规的方式启动线程时(所以使用线程或者其他什么,或者让原生插件或者操作系统或者其他什么情况),你做的一切都“就像你平常做的一样”。
一切都很顺利。
作为一个蹩脚的Unity程序员,我只知道足够的C#来完成一天的工作,我一直认为上面的Async/Await模式实际上会启动另一个线程。
事实上,当您使用natty async/wait模式时,上面的代码是真的启动了另一个线程,还是ct/.net使用其他方法来完成任务?
也许它在Unity引擎中的工作方式与“普遍使用C#”不同,或者有什么特别之处?(IDK?)
注意,在Unity中,它是否是一个线程会极大地影响到您必须如何处理接下来的步骤。所以才有了问题。
问题:我知道有很多关于“等待一个线程”的讨论,但是,(1)我从未见过在Unity设置中讨论/回答这个问题(这有什么区别吗?idk?)(2)我简直从来没有见过一个明确的答案!
这篇文章:任务(仍然)不是线程,异步不是并行的,可能会帮助您理解在引擎盖下面发生了什么。简而言之,为了使任务在单独的线程上运行,您需要调用
Task.Run(()=>{// the work to be done on a separate thread. });
然后你可以在任何需要的地方等待这个任务。
回答你的问题
“事实上,当您使用natty async/wait模式时,上面的代码是真的启动了另一个线程,还是CUTER/.NET使用了其他方法来完成任务?”
不-不是的。
如果你做了
await Task.Run(()=> cws.ConnectAsync(u, CancellationToken.None));
则
作为对评论的回答,这里是修改后的代码,并作了更多的解释:
async void SendExplosionInfo() {
cws = new ClientWebSocket();
try {
var myConnectTask = Task.Run(()=>cws.ConnectAsync(u, CancellationToken.None));
// more code running...
await myConnectTask; // here's where it will actually stop to wait for the completion of your task.
Scene.NewsFromServer("done!"); // class function to go back to main tread
}
catch (Exception e) { ... }
}
但是,您可能不需要在单独的线程上使用它,因为您正在执行的异步工作不受CPU限制(或者看起来是这样)。所以你应该可以接受
try {
var myConnectTask =cws.ConnectAsync(u, CancellationToken.None);
// more code running...
await myConnectTask; // here's where it will actually stop to wait for the completion of your task.
Scene.NewsFromServer("done!"); // continue from here
}
catch (Exception e) { ... }
}
然后,它将在相同的线程上执行与上面代码完全相同的操作。它将允许“ConnectAsync”后面的代码执行,并且只会停下来等待“ConnectAsync”的完成,因为“ConnectAsync”不是CPU绑定的(使它在某种意义上是并行的,在其他地方正在做的工作,如网络)将有足够的果汁运行您的任务,除非您的代码在“。。。。”也需要大量的CPU绑定工作,您宁愿并行运行。
另外,您可能希望避免使用async void,因为它只用于顶级函数。尝试在方法签名中使用异步任务。你可以在这里读到更多关于这方面的内容。
不,Async/Await并不意味着-另一个线程。它可以启动另一个线程,但不一定要启动。
在这里您可以找到关于它的非常有趣的帖子:https://blogs.msdn.microsoft.com/benwilli/2015/09/10/tasks-are-still-not-threads-and-async-is-not-parallel/
首先,你的问题的第一个陈述是有问题的。
Unity是单线程的
团结不是单线的;实际上,Unity是一个多线程环境。为什么?只需转到Unity官方网页并在那里阅读:
高性能多线程系统:充分利用今天(和明天)可用的多核处理器,无需繁重的编程。我们支持高性能的新基础由三个子系统组成:C#作业系统,它为编写并行代码提供了一个安全而容易的沙箱;实体组件系统(ECS),默认情况下用于编写高性能代码的模型,以及突发编译器,它生成高度优化的本机代码。
Unity 3D引擎使用一个名为“Mono”的。NET运行时,该运行时本质上是多线程的。对于某些平台,托管代码将转换为本机代码,因此不会有。NET运行时。但是代码本身无论如何都是多线程的。
所以请不要陈述误导性的和技术上不正确的事实。
您所争论的,仅仅是一个声明,即Unity中有一个主线程,它以基于框架的方式处理核心工作负载。这是真的。但这不是什么新的和独特的东西!例如。在。NET Framework(或从3.0开始的。NET Core)上运行的WPF应用程序也有一个主线程(通常称为UI线程),并且工作负载是使用WPF
请注意:我的答案只适用于运行。NET运行时环境(Mono)的这类Unity实例。对于那些将托管C#代码转换为本机C++代码并构建/运行本机二进制文件的实例,我的答案最有可能至少是不准确的。
你写:
当你在另一个线程上做某事时,你经常使用async/wait,因为,嗯,所有优秀的C#程序员都说,这是做这件事的简单方法!
C#中的
抽头用于任意异步操作。一般来说,没有螺纹。我强烈推荐阅读这篇Stephen Cleary的文章,名为“There is no threaded”。(Stephen Cleary是一位著名的异步编程大师,如果您不知道的话。)
使用
事实上,当您使用natty async/wait模式时,上面的代码是真的启动了另一个线程,还是ct/.net使用其他方法来完成任务?
正确答案是:视情况而定。
你看,这相当复杂。但这正是在C#中引入TAP模式和
@agfc声明了一件不太正确的事情:
“这不会在后台线程上运行该方法”
await cws.ConnectAsync(u, CancellationToken.None);
“但这将”
await Task.Run(()=> cws.ConnectAsync(u, CancellationToken.None));
如果 请注意, 更多有趣的阅读: