Been running into some issues with threading and Unity wherein if a thread was running in the background, and the editor calls a reload, say if you edit a script, eventually or immediately, Unity will crash or freeze.
The issue is because all assemblies get reloaded, and therefore there is a dangling pointer for the threaded assembly/dll.
To further complicate the problem, even if a thread has genuinely completed it's main routine, such as in the case of the running an external executable, and closing that executable, or exiting with an exit code returned, the threads are still not properly cleaned up, and can still cause crashing. Aborting, canceling, and even joining to the main thread don't work either. There's still something weird going on as soon as Unity reloads ALL of it's assemblies. The log files always show that Unity successfully completes the reload, but immediately after, we have the dangling pointer.
I am aware that you can block reloading with
EditorApplication.LockReloadAssemblies();
, and even that you can intercept reload with a callback pre reload... But if there is a way to block reloading all together of a specific assemblies, that would solve the crashing problem.
Much simpler would be a folder, say Plugins, where any assembly in there would never recompile.
This problem is not about runtime / play mode, but only inside the Editor, since I am working on production tools & plugins.
Is anyone aware of a solution to this very frustrating problem?
答案 0 :(得分:1)
这是不可能的。我用来包含IronPython内存泄漏的解决方案是将scriptengine放入它自己的appdomain,有效地包含内存泄漏。如果你决定操作编辑器,这是可能的,但如果你在一个线程上有它,你将遇到麻烦而不试图将它发送到主线程。这包括Debug.Log。
答案 1 :(得分:1)
在Unity Editor中使用Thread进行后台工作时,我也遇到了这个问题。我能够通过使用UnityEditor.Callbacks.DidReloadScripts
中止并重新启动线程来解决问题。这是我测试的代码:
using System.Threading;
using UnityEngine;
public static class Manager1
{
public static int Counter = 0;
private static Thread Thread;
static Manager1()
{
ThreadStart();
}
[UnityEditor.Callbacks.DidReloadScripts]
static void DidReload()
{
Restart();
}
static void Task()
{
while (true)
{
Counter++;
Thread.Sleep(100);
}
}
static void Abort()
{
Debug.Log("ABORT");
Thread.Abort();
Thread = null;
}
static void Restart()
{
Abort();
ThreadStart();
}
static void ThreadStart()
{
Thread = new Thread(Task);
Thread.Start();
}
}
但是,请注意我还必须在线程中添加对Thread.Sleep
的调用。我无法找到关于此的任何信息,但我观察到,如果没有那个调用,ThreadAbortException
永远不会在线程中出现,当然线程永远不会结束。