C# 是否可以在Unity Editor中选择性地阻止某些程序集的重新加载?

C# 是否可以在Unity Editor中选择性地阻止某些程序集的重新加载?,c#,multithreading,unity3d,unity5,C#,Multithreading,Unity3d,Unity5,在线程和Unity方面遇到了一些问题,其中,如果线程在后台运行,并且编辑器调用重新加载,例如如果编辑脚本,最终或立即,Unity将崩溃或冻结 问题是因为所有程序集都会重新加载,因此线程程序集/dll有一个悬空指针 使问题进一步复杂化的是,即使线程真正完成了它的主例程,例如在运行外部可执行文件、关闭该可执行文件或返回退出代码退出的情况下,线程仍然并没有正确清理,并且仍然可能导致崩溃。中止、取消甚至加入主线程也不起作用。还有 一旦Unity重新加载所有程序集,就会发生一些奇怪的事情。日志文件总是显示

在线程和Unity方面遇到了一些问题,其中,如果线程在后台运行,并且编辑器调用重新加载,例如如果编辑脚本,最终或立即,Unity将崩溃或冻结

问题是因为所有程序集都会重新加载,因此线程程序集/dll有一个悬空指针

使问题进一步复杂化的是,即使线程真正完成了它的主例程,例如在运行外部可执行文件、关闭该可执行文件或返回退出代码退出的情况下,线程仍然并没有正确清理,并且仍然可能导致崩溃。中止、取消甚至加入主线程也不起作用。还有 一旦Unity重新加载所有程序集,就会发生一些奇怪的事情。日志文件总是显示Unity成功地完成了重新加载,但紧接着,我们得到了悬空指针

我知道您可以使用阻止重新加载

EditorApplication.LockReloadAssemblies();
,即使您可以通过回调预重新加载来拦截重新加载。。。但是,如果有一种方法可以阻止所有特定程序集一起重新加载,则可以解决崩溃问题

更简单的是一个文件夹,比如插件,其中的任何程序集都不会重新编译

这个问题不是关于运行时/播放模式,而是在编辑器内部,因为我正在处理生产工具和插件


有人知道这个令人沮丧的问题的解决方案吗?

这是不可能的。我用来遏制IronPython内存泄漏的解决方案是将scriptengine放入它自己的appdomain中,有效地遏制内存泄漏。如果您决定操纵编辑器,这是可能的,但是如果您在一个线程上有它,您将在不尝试将它分派到主线程的情况下遇到问题。这包括Debug.Log

在使用Unity编辑器中的线程进行一些后台工作时,我也遇到了这个问题。我可以通过使用
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
在线程中永远不会出现,线程当然也永远不会结束。

5.6通过检测dll已重新编译并自动退出播放模式来解决此问题,而不是NPE,它会抛出一条更柔和的消息,说明以下内容的效果:“由于二进制文件的重新编译,播放模式终止。“谢谢你提供的信息。可悲的是,这个问题变得更深了,因为a)问题完全在编辑器中,与播放模式无关;B)我根本不希望dll重新编译,因为我希望它的状态保持不变,即使我想关闭它,它仍然会由于与垃圾收集不一致而导致指针悬空。但是,这确实让我想知道,我是否将启动此线程的类填充到游戏对象中,并将其设置为DontDestroyOnLoad(This);如果那样行的话。那超出了我所知道的。我错了DontDestroyOnLoad。。。这只适用于播放模式。与该游戏对象关联的程序集仍将在任何时候触发重新加载时在编辑器中重新加载。无法从重新加载中排除程序集的疯狂。。。。除非你能,我也不知道怎么做(根据我的经验和我所读的内容,thread.Abort()不是关闭线程的正确方法,而且是危险的。最好使用thread.Interrupt();并执行垃圾收集。thread.Join())也可以接受,但如果线程中的主例程挂起,则会出现其他问题。不过,在重新加载程序集并清理线程时获取回调的想法是个好主意。我认为你是对的。我通常看到的建议是设置一个标志以向线程发送结束信号。我认为thread.Abor的主要问题是这是因为它不能控制线程执行的结束位置——在我的例子中,这并不重要。