Multithreading 统一的线程安全

Multithreading 统一的线程安全,multithreading,unity3d,Multithreading,Unity3d,在Unity中,线程无法操作UnityEngine提供的对象,如transform.position等,这导致了只能从主线程调用get_transform的异常。 然而,这些方法可以在一些异步函数中使用,比如BeginReceive,那么有人能告诉我为什么吗?异步函数不是线程或其他什么 我尝试下面的代码: void Start(){ AsyncCallback callback = new AsyncCallback (demo); callback.BeginInvoke (n

在Unity中,线程无法操作UnityEngine提供的对象,如transform.position等,这导致了只能从主线程调用get_transform的异常。
然而,这些方法可以在一些异步函数中使用,比如BeginReceive,那么有人能告诉我为什么吗?异步函数不是线程或其他什么

我尝试下面的代码:

void Start(){
    AsyncCallback callback = new AsyncCallback (demo);
    callback.BeginInvoke (null, null, null);
}

void demo(IAsyncResult result){
    Debug.Log(Thread.CurrentThread.ManagedThreadId);
    Debug.Log(gb.transform.position.ToString());
}
当我在Unity Editor上运行代码时,它确实会引发异常。然而,当我直接在Android手机上运行此代码时,它没有引发任何异常,代码执行正确

applogcat中的日志显示:

Line 13497: 02-20 14:37:49.973 31027 31697 I Unity   : 3
Line 13501: 02-20 14:37:49.975 31027 31697 I Unity   : (0.0, 0.0, 0.0)

因此,函数似乎在另一个线程而不是主线程上运行,那么有人能告诉我为什么transform会在这种情况下工作吗?

Unity不允许从主线程以外的线程调用大多数API函数。所有事件/消息处理实际上都在主线程上完成

基于
IEnumerator
的协同程序系统有点不成熟,实际上不允许多线程(请记住,即使是.NET 4.5 async/await特性也不一定意味着多线程执行)


如果调用UnityEngine API有效,那么您就在主线程上。

Unity不允许从主线程以外的线程调用大多数API函数,句号。所有事件/消息处理实际上都在主线程上完成

基于
IEnumerator
的协同程序系统有点不成熟,实际上不允许多线程(请记住,即使是.NET 4.5 async/await特性也不一定意味着多线程执行)


如果调用UnityEngine API有效,则您处于主线程。

不允许从与UI API不同的线程调用UI API

这简化了Unity在幕后的工作方式,实际上使其更快

某些异步方法使用事件循环而不是其他线程进行调度。仅仅因为方法是异步的,并不意味着它可以在不同的线程上运行


在Unity中,最明显的例子是协同程序。它们确实异步运行,但在主线程上运行。这是可能的,因为Unity将所有API添加到一个列表中,并在每一帧执行它们。

UI API不允许从与UI API不同的线程调用

这简化了Unity在幕后的工作方式,实际上使其更快

某些异步方法使用事件循环而不是其他线程进行调度。仅仅因为方法是异步的,并不意味着它可以在不同的线程上运行


在Unity中,最明显的例子是协同程序。它们确实异步运行,但在主线程上运行。这是可能的,因为Unity会将所有内容添加到一个列表中,并在每一帧执行它们。

您可以从其他线程调用Unity API,但如果您是在Unity编辑器中运行游戏,则不能。发布版本不检查对Unity API的调用来自哪个线程。我想他们不会费心去避免性能的下降


不过,我自己还没有测试过这么多。Unity文档非常清楚,API不是线程安全的。因此,绝对不要进行任何属性分配或调用来改变其他线程的游戏状态。仅读取值可能是可以的,但这取决于UnityEngine未知的内部缓存行为,即哈希表/字典不利于多线程。

您可以从其他线程调用Unity API,但如果您在Unity编辑器中运行游戏,则不能。发布版本不检查对Unity API的调用来自哪个线程。我想他们不会费心去避免性能的下降


不过,我自己还没有测试过这么多。Unity文档非常清楚,API不是线程安全的。因此,绝对不要进行任何属性分配或调用来改变其他线程的游戏状态。仅仅读取值可能没问题,但这取决于UnityEngine未知的内部缓存行为,即哈希表/字典不利于多线程。

“在一些异步函数(如BeginReceive)中,C#中有许多异步函数。你试穿了哪一件?你在做什么,需要你使用另一个线程?我只是想知道BeginReceive应该是一个线程,但我可以使用UnityEngine提供的方法,没有例外。BeginReceive从哪里开始?哪一班?其中有许多来自不同的C#API/classes.Socket和System.Net.scokets。您没有包含您的代码,因此我无法判断发生了什么情况,但如果您没有看到异常,这只是意味着代码没有在其他线程上运行。至于在另一个线程中调用/使用Unity API,请看下面的内容:“在一些异步函数(如BeginReceive)中,C#中有许多异步函数。你试穿了哪一件?你在做什么,需要你使用另一个线程?我只是想知道BeginReceive应该是一个线程,但我可以使用UnityEngine提供的方法,没有例外。BeginReceive从哪里开始?哪一班?其中有许多来自不同的C#API/classes.Socket和System.Net.scokets。您没有包含您的代码,因此我无法判断发生了什么情况,但如果您没有看到异常,这只是意味着代码没有在其他线程上运行。至于在另一个线程中调用/使用Unity API,请看这个。我尝试调用函数
Debug.Log(Thread.CurrentThread.ManagedThreadId)
来检查这两个函数中的线程id,这是不同的。我给出了上面的演示代码,你能告诉我为什么吗?我只能在Windows上测试代码-它给出了不同线程id的预期结果和一个错误。我在android手机上运行此代码并附加上面的日志。我尝试调用函数
Debug.log(thread.CurrentThread.ManagedThreadId)
来检查两个函数中的线程id,这是不同的。我给你上面的演示代码,你可以吗