我正在通过 Assembly.LoadFile 使用运行时 dll 初始化来为我的项目加载其他视口。我已经以这种方式成功启动了 WPF 表单和 CS-SDL 表单(均构建为 dll),但 MonoGame 表单在 60 秒后给了我一个错误。运行:
托管调试助手“ContextSwitchDeadlock”检测到问题。CLR 在 60 秒内无法从 COM 上下文 0x5b16f8 转换到 COM 上下文 0x5b1920。拥有目标上下文/单元的线程很可能要么进行非泵送等待,要么处理非常长时间运行的操作而不泵送 Windows 消息。等等
插件(作为类库构建的表单)初始化代码:
foreach (PluginInfo plginfo in _gameManager.XmlReader.ReadViewPlugins(System.Environment.CurrentDirectory + "\\plugins\\plugins.xml"))
{
if (plginfo.Correct)
{
//create new thread for every plugin
Thread thread = new Thread(RunViewControlPlugin);
thread.Name = plginfo.Name;
//set it to single-threaded if plugin requires so
if (plginfo.STA)
thread.SetApartmentState(ApartmentState.STA);
thread.Start(plginfo);
}
}
RunViewControl 方法:
void RunViewControlPlugin(object data)
{
PluginInfo plginfo = (PluginInfo)data;
string path = System.Environment.CurrentDirectory + "\\plugins\\" + plginfo.FileName;
//load assembly from the path and create instance of the required type
Assembly assembly = Assembly.LoadFile(path);
Type type = assembly.GetType(plginfo.AssemblyData);
IViewControlPlugin plugin = (IViewControlPlugin)Activator.CreateInstance(type);
lock(locker)
{
_viewcontrolpluginList.Add(plugin);
}
//on shutdown close dispatcher, remove plugin from the active plugins list and unsubscribe
EventHandler handler = null;
handler = (s, e) => {
if (plginfo.DispatcherNeeded)
System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvokeShutdown(System.Windows.Threading.DispatcherPriority.Background);
_gameManager.DebugLogger.LogGeneralInfo(plginfo.Name+" stopped.");
_viewcontrolpluginList.Remove(plugin);
plugin.Closed -= handler;
};
plugin.Closed += handler;
//send manager instances to the plugin
plugin.AddGameDataManager(_gameDataManager);
plugin.AddGameManager(_gameManager);
_gameManager.DebugLogger.LogGeneralInfo(plginfo.Name + " started.");
//start dispatcher (wpf forms require dispatcher to run)
if (plginfo.DispatcherNeeded)
System.Windows.Threading.Dispatcher.Run();
plugin.Start();
}
我想知道如何解决这个问题(除了关闭 MDA)。我应该明确实施消息泵送吗?
表单做得很好,它可以看到鼠标/键盘事件并且可以移动。唯一的问题是可能与这种情况有关的内存泄漏(MDA 描述表明它可能导致内存泄漏)。
更新:为 XNA 线程设置 STA 似乎可以抑制这个错误,尽管我不清楚为什么。也许我应该更深入地研究 Windows 内部机制。