private void bwr_InitializeTorque(object sender, DoWorkEventArgs e) { Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; //foreach (string file in // Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + @"shaders\procedural").Where(file => !Path.GetFileName(file).StartsWith("."))) // File.Delete(file); MObjectCreateDefs.Clear(); try { SafeNativeMethods.SetUpDynamicDLL(_mDll); } catch (Exception err) { LastError = err; _mStop = true; if (_ScriptExtensions_Allow) { csFactory.Instance.StopMonitoring(); } return; } //create a list of pointers for our parameters List <IntPtr> myp = new List <IntPtr> { Marshal.StringToCoTaskMemAnsi(Assembly.GetExecutingAssembly().Location) }; //Add the pointer to a managed memory string containing the location of the Assembly. //Create a managed memory string object and put our command line parameters in each one, //then add the pointer to that object into our list. myp.AddRange(_mCmdParams.Select(Marshal.StringToCoTaskMemAnsi)); //Now, this if fun stuff, we need to save the pointer to the instance eval delegate //and save it to a static variable so the DotNet's Garabage collection doesn't //decide to through it away on a cleanup since no object inside of DotNet //will have a reference to it. _mLocalhandleRegisterSimObjectCallback = RegisterSimObject_Callback; GC.SuppressFinalize(_mLocalhandleRegisterSimObjectCallback); _mLocalhandleWleEngineCallBack = WLE_EngineCallBack; GC.SuppressFinalize(_mLocalhandleWleEngineCallBack); _mWLE_GlobalFunctionCallBack = WLE_GlobalFunctionCallBack; GC.SuppressFinalize(_mWLE_GlobalFunctionCallBack); _mWLE_ExportVariablesAsSettings = WLE_ExportVariablesAsSettings; GC.SuppressFinalize(_mWLE_ExportVariablesAsSettings); _mWLE_isFunction_Callback = isFunction_Callback; GC.SuppressFinalize(_mWLE_isFunction_Callback); _mWLE_gisFunction_Callback = gisFunction_Callback; GC.SuppressFinalize(_mWLE_gisFunction_Callback); _mWLE_setIcon_Callback = SetIconCallBack; GC.SuppressFinalize(_mWLE_setIcon_Callback); //We make an extern call to the T3D dll passing our pointers so the T3D can //make callbacks. SafeNativeMethods.mSetHandler_SimIdDictionary(_mLocalhandleRegisterSimObjectCallback); SafeNativeMethods.mSetEngineCallback(_mLocalhandleWleEngineCallBack); SafeNativeMethods.mSetGlobalFunctionCallback(_mWLE_GlobalFunctionCallBack); SafeNativeMethods.mSetExportVariablesAsSettings(_mWLE_ExportVariablesAsSettings); SafeNativeMethods.mSetWLE_IsFunction(_mWLE_isFunction_Callback); SafeNativeMethods.mSetWLE_gIsFunction(_mWLE_gisFunction_Callback); SafeNativeMethods.m_SetWLE_setIcon(_mWLE_setIcon_Callback); //Initialize the T3D dll and capture its window handle. SafeNativeMethods.mdnt_torque_engineinit(myp.Count, myp.ToArray(), _mhinstance); //if (WindowIcon != null) // SetParentIcon(WindowIcon); foreach (IntPtr ptr in myp) { Marshal.FreeCoTaskMem(ptr); } //We make one cal to the engine tick before doing anything else at this point //so Torque can set everything up. SafeNativeMethods.mtorque_enginetick(); //Loop until told to stop. //I use to have this in a try/catch block, but since errors through from calling a managed memory object //are considered "Hard" errors, a try catch block will not catch them. //Since Torque's console is not multi-threaded we have to be careful on async calls, i.e. calls //made to torque not as a result of torque calling a exported function, but instead of a //csharp function running in a seperate thread. //So to prevent corruption, only allow async functions to make calls back to Torque when it is //in an idle state, i.e. not "Ticking". This way there is no way to calls can enter the same Torque //function at the same time and cause memory corruption. while (!_mStop) { lock (_tick) SafeNativeMethods.mtorque_enginetick(); } if (_ScriptExtensions_Allow) { csFactory.Instance.StopMonitoring(); } SafeNativeMethods.mtorque_enginesignalshutdown(); SafeNativeMethods.mtorque_enginetick(); SafeNativeMethods.mtorque_enginetick(); SafeNativeMethods.mtorque_enginetick(); SafeNativeMethods.mtorque_enginetick(); //Commenting this out for now, causing a memory corruption issue. SafeNativeMethods.mtorque_engineshutdown(); SafeNativeMethods.mClearEngineCallback(); SafeNativeMethods.mClearHandler_SimIdDictionary(); SafeNativeMethods.mClearGlobalFunctionCallback(); SafeNativeMethods.mClearExportVariablesAsSettings(); SafeNativeMethods.mClearWLE_IsFunction(); SafeNativeMethods.mClearWLE_gIsFunction(); SafeNativeMethods.mClearWLE_setIcon(); GC.ReRegisterForFinalize(_mLocalhandleRegisterSimObjectCallback); _mLocalhandleRegisterSimObjectCallback = null; GC.ReRegisterForFinalize(_mLocalhandleWleEngineCallBack); _mLocalhandleWleEngineCallBack = null; GC.Collect(); ShutDownCleanUp(); }
private void bwr_InitializeTorque(object sender, DoWorkEventArgs e) { Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; //foreach (string file in // Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + @"shaders\procedural").Where(file => !Path.GetFileName(file).StartsWith("."))) // File.Delete(file); MObjectCreateDefs.Clear(); try { SafeNativeMethods.SetUpDynamicDLL(_mDll); } catch (Exception err) { LastError = err; _mStop = true; if (_ScriptExtensions_Allow) csFactory.Instance.StopMonitoring(); return; } //create a list of pointers for our parameters List<IntPtr> myp = new List<IntPtr> {Marshal.StringToCoTaskMemAnsi(Assembly.GetExecutingAssembly().Location)}; //Add the pointer to a managed memory string containing the location of the Assembly. //Create a managed memory string object and put our command line parameters in each one, //then add the pointer to that object into our list. myp.AddRange(_mCmdParams.Select(Marshal.StringToCoTaskMemAnsi)); //Now, this if fun stuff, we need to save the pointer to the instance eval delegate //and save it to a static variable so the DotNet's Garabage collection doesn't //decide to through it away on a cleanup since no object inside of DotNet //will have a reference to it. _mLocalhandleRegisterSimObjectCallback = RegisterSimObject_Callback; GC.SuppressFinalize(_mLocalhandleRegisterSimObjectCallback); _mLocalhandleWleEngineCallBack = WLE_EngineCallBack; GC.SuppressFinalize(_mLocalhandleWleEngineCallBack); _mWLE_GlobalFunctionCallBack = WLE_GlobalFunctionCallBack; GC.SuppressFinalize(_mWLE_GlobalFunctionCallBack); _mWLE_ExportVariablesAsSettings = WLE_ExportVariablesAsSettings; GC.SuppressFinalize(_mWLE_ExportVariablesAsSettings); _mWLE_isFunction_Callback = isFunction_Callback; GC.SuppressFinalize(_mWLE_isFunction_Callback); _mWLE_gisFunction_Callback = gisFunction_Callback; GC.SuppressFinalize(_mWLE_gisFunction_Callback); _mWLE_setIcon_Callback = SetIconCallBack; GC.SuppressFinalize(_mWLE_setIcon_Callback); //We make an extern call to the T3D dll passing our pointers so the T3D can //make callbacks. SafeNativeMethods.mSetHandler_SimIdDictionary(_mLocalhandleRegisterSimObjectCallback); SafeNativeMethods.mSetEngineCallback(_mLocalhandleWleEngineCallBack); SafeNativeMethods.mSetGlobalFunctionCallback(_mWLE_GlobalFunctionCallBack); SafeNativeMethods.mSetExportVariablesAsSettings(_mWLE_ExportVariablesAsSettings); SafeNativeMethods.mSetWLE_IsFunction(_mWLE_isFunction_Callback); SafeNativeMethods.mSetWLE_gIsFunction(_mWLE_gisFunction_Callback); SafeNativeMethods.m_SetWLE_setIcon(_mWLE_setIcon_Callback); //Initialize the T3D dll and capture its window handle. SafeNativeMethods.mdnt_torque_engineinit(myp.Count, myp.ToArray(), _mhinstance); //if (WindowIcon != null) // SetParentIcon(WindowIcon); foreach (IntPtr ptr in myp) Marshal.FreeCoTaskMem(ptr); //We make one cal to the engine tick before doing anything else at this point //so Torque can set everything up. SafeNativeMethods.mtorque_enginetick(); //Loop until told to stop. //I use to have this in a try/catch block, but since errors through from calling a managed memory object //are considered "Hard" errors, a try catch block will not catch them. //Since Torque's console is not multi-threaded we have to be careful on async calls, i.e. calls //made to torque not as a result of torque calling a exported function, but instead of a //csharp function running in a seperate thread. //So to prevent corruption, only allow async functions to make calls back to Torque when it is //in an idle state, i.e. not "Ticking". This way there is no way to calls can enter the same Torque //function at the same time and cause memory corruption. while (!_mStop) { lock (_tick) SafeNativeMethods.mtorque_enginetick(); } if (_ScriptExtensions_Allow) csFactory.Instance.StopMonitoring(); SafeNativeMethods.mtorque_enginesignalshutdown(); SafeNativeMethods.mtorque_enginetick(); SafeNativeMethods.mtorque_enginetick(); SafeNativeMethods.mtorque_enginetick(); SafeNativeMethods.mtorque_enginetick(); //Commenting this out for now, causing a memory corruption issue. SafeNativeMethods.mtorque_engineshutdown(); SafeNativeMethods.mClearEngineCallback(); SafeNativeMethods.mClearHandler_SimIdDictionary(); SafeNativeMethods.mClearGlobalFunctionCallback(); SafeNativeMethods.mClearExportVariablesAsSettings(); SafeNativeMethods.mClearWLE_IsFunction(); SafeNativeMethods.mClearWLE_gIsFunction(); SafeNativeMethods.mClearWLE_setIcon(); GC.ReRegisterForFinalize(_mLocalhandleRegisterSimObjectCallback); _mLocalhandleRegisterSimObjectCallback = null; GC.ReRegisterForFinalize(_mLocalhandleWleEngineCallBack); _mLocalhandleWleEngineCallBack = null; GC.Collect(); ShutDownCleanUp(); }