Thank you very much, Willy. I really appreciate all of the help. I have
tried these and other methods to get this windows service functioning,
however, I've been unsuccessful. I think I'm going to have to assume that
this component just doesn't function as a multithreaded windows service.
Without threading I can the windows service to run properly so perhaps I can
just create 15 windows services (not perfered). I require this application
to run continually so windows service is the way to go. Alternatively I may
just have to have the multithreaded windows form app running in a terminal
service session (again not perfered). Anyways, I really appreciate all of
your help. Thank you very much.
Jay
Willy Denoyette said:
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iTrunk);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomingCall);
Oh, this ....
_IADXVoiceEvents
confirms what I've said before, the component is most certainly an ActiveX
control NOT a .NET component, the IADXVoiceEvents denotes COM
ConnectionPoint interface (probably a Windowless ATL Control interface) .
Following summarizes what you need to take care of when hosting such
control:
First, AX Controls are "Apartment" threaded, so you better initialize your
threads to enter an STA, else your objects will end on the default STA
thread created by COM.
Second, STA threads should to pump the message queue (COM message only),
this is required by the Finalizer thread, who runs in the MTA, to be able
to release the RCW when you're done with the object.
It's however not required by COM interop, as long as you don't need to
marshal across incomaptible apartments, and here you don't.
What you have to do is keep your threads pumping COM messages, this can be
achieved by calling a pumping wait.
For instance you could have a loop that calls Thread.Join with a timeout,
or better a Wait on an event with a timeout, this way you can do stuff
like detach your eventhandlers release the COM objects and stop your
threads in your service OnStop handler.
Following snippet, illustrates most of this, (not tested!)...
const int threads = 15;
ManualResetEvent[] mre = new ManualResetEvent[threads];
...
Thread[] t = new Thread[threads];
for (int i = 0; i < threads; i++)
{
signals
= new ManualResetEvent(false);
t = new Thread(new
ParameterizedThreadStart(ProcessingThread),200000);
t.SetApartmentState(ApartmentState.STA);
t.IsBackground=true;
t.Start(mre);
}
public void ProcessingThread(object shutdownEvent)
{
....
ADXVoice1.InCommingCall += new
_IADXVoiceEvents_InCommingCallEventHandler(OnIncomingCall);
// Wait 100 msec. for event to be set, leave the loop when set,
WaitOne pumps COM messages
while (!((ManualResetEvent)(shutdownEvent)).WaitOne(100, true))
;
// signaled to stop, detach handler and release COM object
ADXVoice1.InCommingCall -= new
_IADXVoiceEvents_InCommingCallEventHandler(OnIncomingCall);
Marshal.ReleaseComObject(ADXVoice1);
}
...
protected override void OnStop()
{
for (int n = 0; n < threads; n++)
mre[n].Set();
// Wait for threads to end.... use Join or whatever other
synchronization primitive,
// keeping in mind that you need to return from OnStop before
the SCM gets nervous
}
Willy.
[/QUOTE]