I want to create a C# .net app that will be run as a service. That app will make calls to a COM component. From what I understand (based on SO posts here, here, and here), in order for my code to work I need to start a new thread to run my code on with apartment state == STA.
Consider the following:
public class MessagePumpManager
{
private readonly Thread messagePump;
private AutoResetEvent messagePumpRunning = new AutoResetEvent(false);
SimconnectToJson eventsToJson = null;
public MessagePumpManager()
{
// start message pump in its own thread
messagePump = new Thread(RunMessagePump) { Name = "ManualMessagePump" };
messagePump.SetApartmentState(ApartmentState.STA);
messagePump.Start();
messagePumpRunning.WaitOne();
}
// Message Pump Thread
private void RunMessagePump()
{
Console.WriteLine("Message Pump Thread apt state " + messagePump.GetApartmentState().ToString()
+ " started with handle " + messageHandler.Handle.ToString());
// Create control to handle windows messages
MessageHandler messageHandler = new MessageHandler();
// Attempt to initialize COM object...
Type myComObjectType = typeof(Microsoft.FlightSimulator.SimConnect.SimConnect);
System.Reflection.ConstructorInfo ctorInfo = myComObjectType.GetConstructor(new Type[] { typeof(string), typeof(IntPtr), typeof(uint), typeof(System.Threading.WaitHandle), typeof(uint) });
try
{
Microsoft.FlightSimulator.SimConnect.SimConnect simconnect
= (Microsoft.FlightSimulator.SimConnect.SimConnect)ctorInfo.Invoke(new object[] { "Service Connection", messageHandler.Handle, (uint)0x0402, null, (uint)0 });
Console.WriteLine("Successful invocation to create new COM object");
}
catch (Exception ex)
{
Console.WriteLine("Error attempting to create COM object");
Console.WriteLine("");
Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
}
messagePumpRunning.Set();
Application.Run();
}
}
If the code's executable is run from the UI, it works. If it's run as a service, it fails with an error:
Exception has been thrown by the target of an invocation.
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
According to the log output, the ApartmentState of my thread is STA, and I know that when run from a UI my constructor invoke is correct. Yet I'm clearly doing something wrong.
Aucun commentaire:
Enregistrer un commentaire