从事件处理程序调用时,Unity Coroutine 未启动
Unity Coroutine is not starting when called from an event handler
我在尝试从事件处理程序的主体调用 StartCoroutine 时遇到问题。我希望在控制台上打印以下内容,而不是它只打印“之前”并且不会启动协程:
之前
里面
工作
之后
private void Awake()
{
socket.OnMessage += (sender,e) => {
Debug.Log("before");
StartCoroutine(handleIncommingMessages(sender,e));
Debug.Log("after");
};
}
public IEnumerator handleIncommingMessages(object sender, MessageEventArgs e) {
Debug.Log("inside");
yield return new WaitForSeconds(3f);
Debug.Log("working");
}
事件调用完成后协程被丢弃可能存在问题。我不知道如何修复它 - 但如果您使用的是较新版本的 Unity,则可以改用任务:
private void Awake()
{
// We add async so that we can use the `await` call.
socket.OnMessage += async (sender,e) => {
Debug.Log("before");
// Force it to await when the incoming message as not to close the thread
await handleIncommingMessages(sender, e);
Debug.Log("after");
};
}
public async Task handleIncommingMessages(object sender, MessageEventArgs e) {
Debug.Log("inside");
await Task.Delay(1000);
Debug.Log("working");
}
如果这不起作用,请尝试:
public async void handleIncommingMessages
而不是 Task
这个协程只能在主线程中运行。你必须将你要执行的协程的方法注入到主线程中。
通常当您尝试在另一个线程中 运行 它时,您会收到此错误:
UnityException: IsObjectMonoBehaviour 只能从主线程调用。
我通过定义 public 列表并使用更新方法解决了这个问题。
List<Action> threadPumpList = new List<Action>();
private void Update()
{
while (threadPumpList.Count > 0)
{
threadPumpList[0].Invoke();
threadPumpList.RemoveAt(0);
}
}
public void WriteTestMessage()
{
Debug.Log("Hello World.")
}
public void Test()
{
threadPumpList.Add(() => WriteTestMessage());
}
你可以这样用。
List<IEnumerator> threadPumpList = new List<IEnumerator>();
private void Update()
{
while (threadPumpList.Count > 0)
{
StartCoroutine(threadPumpList[0]);
threadPumpList.RemoveAt(0);
}
}
private void Awake()
{
//socket.OnMessage += (sender,e) =>
new Thread(() => //You should use socket right here.
{
Debug.Log("before");
threadPumpList.Add(handleIncommingMessages(null, ""));
Debug.Log("after");
}).Start();
}
public IEnumerator handleIncommingMessages(object sender, string e) //I changed parameters for testing.
{
Debug.Log("inside");
yield return new WaitForSeconds(3f);
Debug.Log("working");
}
当我测试它时,输出是这样的:
-之前
-后
-里面
(等待 3 秒)
-工作
我在尝试从事件处理程序的主体调用 StartCoroutine 时遇到问题。我希望在控制台上打印以下内容,而不是它只打印“之前”并且不会启动协程:
之前
里面
工作
之后
private void Awake() { socket.OnMessage += (sender,e) => { Debug.Log("before"); StartCoroutine(handleIncommingMessages(sender,e)); Debug.Log("after"); }; } public IEnumerator handleIncommingMessages(object sender, MessageEventArgs e) { Debug.Log("inside"); yield return new WaitForSeconds(3f); Debug.Log("working"); }
事件调用完成后协程被丢弃可能存在问题。我不知道如何修复它 - 但如果您使用的是较新版本的 Unity,则可以改用任务:
private void Awake()
{
// We add async so that we can use the `await` call.
socket.OnMessage += async (sender,e) => {
Debug.Log("before");
// Force it to await when the incoming message as not to close the thread
await handleIncommingMessages(sender, e);
Debug.Log("after");
};
}
public async Task handleIncommingMessages(object sender, MessageEventArgs e) {
Debug.Log("inside");
await Task.Delay(1000);
Debug.Log("working");
}
如果这不起作用,请尝试:
public async void handleIncommingMessages
而不是 Task
这个协程只能在主线程中运行。你必须将你要执行的协程的方法注入到主线程中。
通常当您尝试在另一个线程中 运行 它时,您会收到此错误: UnityException: IsObjectMonoBehaviour 只能从主线程调用。
我通过定义 public 列表并使用更新方法解决了这个问题。
List<Action> threadPumpList = new List<Action>();
private void Update()
{
while (threadPumpList.Count > 0)
{
threadPumpList[0].Invoke();
threadPumpList.RemoveAt(0);
}
}
public void WriteTestMessage()
{
Debug.Log("Hello World.")
}
public void Test()
{
threadPumpList.Add(() => WriteTestMessage());
}
你可以这样用。
List<IEnumerator> threadPumpList = new List<IEnumerator>();
private void Update()
{
while (threadPumpList.Count > 0)
{
StartCoroutine(threadPumpList[0]);
threadPumpList.RemoveAt(0);
}
}
private void Awake()
{
//socket.OnMessage += (sender,e) =>
new Thread(() => //You should use socket right here.
{
Debug.Log("before");
threadPumpList.Add(handleIncommingMessages(null, ""));
Debug.Log("after");
}).Start();
}
public IEnumerator handleIncommingMessages(object sender, string e) //I changed parameters for testing.
{
Debug.Log("inside");
yield return new WaitForSeconds(3f);
Debug.Log("working");
}
当我测试它时,输出是这样的:
-之前 -后 -里面 (等待 3 秒) -工作