From cbf2a0fac68b6a3bed075b5bf93eda2886958d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Fri, 2 Dec 2005 18:09:57 +0000 Subject: [PATCH] Rewritten Debugger.MTA2STA git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@819 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Debugger/Internal/MTA2STA.cs | 169 +++++++++--------- .../Debugger/Internal/ManagedCallbackProxy.cs | 2 +- 2 files changed, 87 insertions(+), 84 deletions(-) diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs index d8577956ae..bd7db8cddc 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs @@ -11,122 +11,125 @@ using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; -using Debugger.Interop.CorDebug; - -namespace Debugger.Interop.CorDebug +namespace Debugger { + delegate object MethodInvokerWithReturnValue(); + class MTA2STA - { + { Form hiddenForm; IntPtr hiddenFormHandle; - object targetObject = null; - string functionName = null; - Object[] functionParameters = null; - - System.Threading.Thread MTAThread; - - static object OnlyOneAtTimeLock = new Object(); - static object DataLock = new Object(); - object returnValue; - public MTA2STA() { hiddenForm = new Form(); + // Force handle creation hiddenFormHandle = hiddenForm.Handle; } - void TraceMsg(string msg) + static void TraceMsg(string msg) { //System.Console.WriteLine("MTA2STA: " + msg); } - public object CallInSTA (object targetObject, string functionName, object[] functionParameters) + // Try to avoid this since it will catch exceptions and it is slow + public object CallInSTA(object targetObject, string functionName, object[] functionParameters) { - lock (OnlyOneAtTimeLock) { - TraceMsg("call to process: " + functionName + " {"); - - lock (DataLock) { - this.targetObject = targetObject; - this.functionName = functionName; - this.functionParameters = functionParameters; - } - - MTAThread = System.Threading.Thread.CurrentThread; - if (hiddenForm.InvokeRequired == true) { - IAsyncResult async = hiddenForm.BeginInvoke(new EventHandler(PerformCall)); - //while (async.AsyncWaitHandle.WaitOne(1000,true) == false) { - // System.Console.WriteLine("Waiting for callback..."); - //} - if (async.AsyncWaitHandle.WaitOne(1000,true) == false) { - System.Console.WriteLine("Callback time out! Unleashing debugger thread."); - } + return CallInSTA(delegate { return InvokeMethod(targetObject, functionName, functionParameters); }); + } + + public void CallInSTA(MethodInvoker callDelegate) + { + CallInSTA(delegate { callDelegate(); return null; }, true); + } + + public object CallInSTA(MethodInvokerWithReturnValue callDelegate) + { + return CallInSTA(callDelegate, true); // TODO: Make it false once it is safe + } + + object CallInSTA(MethodInvokerWithReturnValue callDelegate, bool mayAbandon) + { + if (hiddenForm.InvokeRequired == true) { + IAsyncResult async = hiddenForm.BeginInvoke(callDelegate); + // Firsy try... give it 1 second to run + if (async.AsyncWaitHandle.WaitOne(1000, true)) { + return hiddenForm.EndInvoke(async); } else { - PerformCall(hiddenForm, EventArgs.Empty); + // Abandon the call if possible + if (mayAbandon) { + System.Console.WriteLine("Callback time out! Unleashing thread."); + return null; + } else { + System.Console.WriteLine("Warring: Call in STA is taking too long"); + return hiddenForm.EndInvoke(async); // Keep waiting + } } + } else { + return callDelegate(); + } + } - TraceMsg("} // MTA2STA: call processed: " + functionName); + public static object MarshalParamTo(object param, Type outputType) + { + if (param is IntPtr) { + return MarshalIntPtrTo((IntPtr)param, outputType); + } else { + return param; } - return returnValue; } - - void PerformCall(object sender, EventArgs e) + + public static object MarshalIntPtrTo(IntPtr param, Type outputType) { - returnValue = Call(targetObject, functionName, functionParameters); + // IntPtr requested as output (must be before the null check so that we pass IntPtr.Zero) + if (outputType == typeof(IntPtr)) { + return param; + } + // The parameter is null pointer + if ((IntPtr)param == IntPtr.Zero) { + return null; + } + // String requested as output + if (outputType == typeof(string)) { + return Marshal.PtrToStringAuto((IntPtr)param); + } + // Marshal a COM object + return Marshal.GetTypedObjectForIUnknown((IntPtr)param, outputType); } - - public object Call (object targetObject, string functionName, object[] functionParameters) + + /// + /// Uses reflection to call method. Automaticaly marshals parameters. + /// + /// Targed object which contains the method. In case of static mehod pass the Type + /// The name of the function to call + /// Parameters which should be send to the function. Parameters will be marshaled to proper type. + /// Return value of the called function + public static object InvokeMethod(object targetObject, string functionName, object[] functionParameters) { MethodInfo method; - object[] outputParams; - lock (DataLock) { - object[] inputParams = functionParameters; - if (targetObject is Type) { - method = ((Type)targetObject).GetMethod(functionName); - } else { - method = targetObject.GetType().GetMethod(functionName); - } - ParameterInfo[] outputParamsInfo = method.GetParameters(); - outputParams = null; - if (outputParamsInfo != null) { - outputParams = new object[outputParamsInfo.Length]; - for (int i = 0; i < outputParams.Length; i++) { - if (inputParams[i] == null) { - outputParams[i] = null; - } else if (inputParams[i] is IntPtr) { - if (outputParamsInfo[i].ParameterType == typeof(IntPtr)) { - outputParams[i] = inputParams[i]; - } else if ((IntPtr)inputParams[i] == IntPtr.Zero) { - outputParams[i] = null; - } else if (outputParamsInfo[i].ParameterType == typeof(string)) { - outputParams[i] = Marshal.PtrToStringAuto((IntPtr)inputParams[i]); - } else { - try{ - outputParams[i] = null; - outputParams[i] = Marshal.GetTypedObjectForIUnknown((IntPtr)inputParams[i], outputParamsInfo[i].ParameterType); - } catch (System.Exception exception) { - throw new Debugger.DebuggerException("Marshaling of argument " + i.ToString() + " of " + functionName + " failed.", exception); - } - } - } else { - outputParams[i] = inputParams[i]; - } - } - } + if (targetObject is Type) { + method = ((Type)targetObject).GetMethod(functionName); + } else { + method = targetObject.GetType().GetMethod(functionName); + } + + ParameterInfo[] methodParamsInfo = method.GetParameters(); + object[] convertedParams = new object[methodParamsInfo.Length]; + + for (int i = 0; i < convertedParams.Length; i++) { + convertedParams[i] = MarshalParamTo(functionParameters[i], methodParamsInfo[i].ParameterType); } - TraceMsg ("Invoke " + functionName + "{"); - object returnValue = null; + + TraceMsg ("Invoking " + functionName + "..."); try { if (targetObject is Type) { - returnValue = method.Invoke(null, outputParams); + return method.Invoke(null, convertedParams); } else { - returnValue = method.Invoke(targetObject, outputParams); + return method.Invoke(targetObject, convertedParams); } } catch (System.Exception exception) { throw new Debugger.DebuggerException("Invoke of " + functionName + " failed.", exception); } - TraceMsg ("} \\\\ Invoke"); - return returnValue; } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallbackProxy.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallbackProxy.cs index 21c607bfaf..d68cbd31d4 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallbackProxy.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallbackProxy.cs @@ -46,7 +46,7 @@ namespace Debugger if (debugger.RequiredApartmentState == ApartmentState.STA) { mta2sta.CallInSTA(realCallback, function, parameters); } else { - mta2sta.Call(realCallback, function, parameters); + MTA2STA.InvokeMethod(realCallback, function, parameters); } }