469,946 Members | 1,928 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,946 developers. It's quick & easy.

Application.Run() In a Windows Service

I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM component
I a using in the app (required for message loop). I have created a windows
service from VStudio 2005 template. What is the windows service replacement
for Application.Run()?
May 16 '07 #1
28 6908

<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
>I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM component
I a using in the app (required for message loop). I have created a windows
service from VStudio 2005 template. What is the windows service
replacement for Application.Run()?
ServiceBase.Run(new service_class); maybe,
but you have to write class (service_class) with OnStart (here you must
call your main code) , OnPause, OnStop methods that inherites
System.ServiceProcess.ServiceBase

D
May 16 '07 #2
Thanks a lot. I have tried, however, no luck. For some reason this com
component just wont function without application.run... which wont work in
the win service.
"Dubravko Sever" <Du******************@foi.hrwrote in message
news:f2**********@news1.carnet.hr...
>
<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
>>I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM
component I a using in the app (required for message loop). I have
created a windows service from VStudio 2005 template. What is the windows
service replacement for Application.Run()?
ServiceBase.Run(new service_class); maybe,
but you have to write class (service_class) with OnStart (here you must
call your main code) , OnPause, OnStop methods that inherites
System.ServiceProcess.ServiceBase

D


May 16 '07 #3
Have you check your account does it have enough permissions? Try to run your
service as a administrator just for testing.

D

<msnews.microsoft.comwrote in message
news:eV**************@TK2MSFTNGP06.phx.gbl...
Thanks a lot. I have tried, however, no luck. For some reason this com
component just wont function without application.run... which wont work in
the win service.
"Dubravko Sever" <Du******************@foi.hrwrote in message
news:f2**********@news1.carnet.hr...
>>
<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
>>>I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM
component I a using in the app (required for message loop). I have
created a windows service from VStudio 2005 template. What is the
windows service replacement for Application.Run()?
ServiceBase.Run(new service_class); maybe,
but you have to write class (service_class) with OnStart (here you must
call your main code) , OnPause, OnStop methods that inherites
System.ServiceProcess.ServiceBase

D



May 16 '07 #4
A Windows service can be started from the command line using Net Start
<yourServiceNameor Net Stop <yourServiceName>. The easiest is to use the
Services MMC.

"msnews.microsoft.com" wrote:
I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM component
I a using in the app (required for message loop). I have created a windows
service from VStudio 2005 template. What is the windows service replacement
for Application.Run()?
May 16 '07 #5
<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
>I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM component
I a using in the app (required for message loop). I have created a windows
service from VStudio 2005 template. What is the windows service
replacement for Application.Run()?


No, Application.Run is not required for COM (apartment style of objects),
all you need is to do is initialize the thread that creates your COM
component to enter the STA, that means you need to set the ApartmentState to
STA before starting the thread, that way you are sure the component runs on
the same thread as the caller and no marshaling is needed.
However, you need to make sure you aren't calling any blocking wait, only
pumping waits are pumping COM messages, this is required to let the
Finalizer thread (running in the MTA) to marshal calls into the STA thread
whenever your RCW needs to be released.

Willy.
May 16 '07 #6
Thanks. Everything within the service runs fine (I write text to a text
file for instance). Only problem is, without application.run, the com
component reference does not function.
"Dubravko Sever" <Du******************@foi.hrwrote in message
news:f2**********@news1.carnet.hr...
Have you check your account does it have enough permissions? Try to run
your service as a administrator just for testing.

D

<msnews.microsoft.comwrote in message
news:eV**************@TK2MSFTNGP06.phx.gbl...
>Thanks a lot. I have tried, however, no luck. For some reason this com
component just wont function without application.run... which wont work
in the win service.
"Dubravko Sever" <Du******************@foi.hrwrote in message
news:f2**********@news1.carnet.hr...
>>>
<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM
component I a using in the app (required for message loop). I have
created a windows service from VStudio 2005 template. What is the
windows service replacement for Application.Run()?

ServiceBase.Run(new service_class); maybe,
but you have to write class (service_class) with OnStart (here you must
call your main code) , OnPause, OnStop methods that inherites
System.ServiceProcess.ServiceBase

D




May 16 '07 #7
Thank you. Threading is STA. Here is an excert of the code that works fine
as a windows form... But, for some reason I can not put it together to work
as a service.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;
using Envox.ADXVoice;
using System.Data.SqlClient;
using System.Configuration;

namespace AnsweringSystem
{
public partial class Form1 : Form
{
private LineHandler[] LineArray;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
int iFromChannel = 0;
int iToChannel = 3; //4 channels

LineArray = new LineHandler[iToChannel - iFromChannel + 1];

for (int iChannel = iFromChannel; iChannel <= iToChannel;
iChannel++)
{
LineHandler Line = new LineHandler();
LineArray[iChannel - iFromChannel] = Line;
Line.iChannel = iChannel;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA);
wrkThread.Name = iChannel.ToString();
wrkThread.Start();
}
}

//Main class to handle individual channels on separate threads
private class LineHandler
{
public int iChannel = -1;
public Thread CurrentThread = null;

private ADXVoiceClass ADXVoice1 = null;

private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
try
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iChannel);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);
}
catch (COMException e)
{
ADXVoice1 = null;
return;
}
catch (Exception e)
{
ADXVoice1 = null;
return;
}

//Start message loop (keeps thread from exiting and allows
ADX to process events, including state changes)
Application.Run();

Marshal.ReleaseComObject(ADXVoice1); //make ADXVoice1
eligible for garbage collection
GC.Collect(); //force Garbage Collection
GC.WaitForPendingFinalizers(); //wait for completion
}

private void OnIncomingCall()
{
//code here to play prompts, branch to other methods, etc.
}

} //End LineHandler class

}
}
I very much appreciate any advice you may have. Thank you very much.

Jay

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:A3**********************************@microsof t.com...
<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
>>I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM
component I a using in the app (required for message loop). I have
created a windows service from VStudio 2005 template. What is the windows
service replacement for Application.Run()?



No, Application.Run is not required for COM (apartment style of objects),
all you need is to do is initialize the thread that creates your COM
component to enter the STA, that means you need to set the ApartmentState
to STA before starting the thread, that way you are sure the component
runs on the same thread as the caller and no marshaling is needed.
However, you need to make sure you aren't calling any blocking wait, only
pumping waits are pumping COM messages, this is required to let the
Finalizer thread (running in the MTA) to marshal calls into the STA thread
whenever your RCW needs to be released.

Willy.


May 16 '07 #8
<msnews.microsoft.comwrote in message
news:Oi**************@TK2MSFTNGP03.phx.gbl...
Thank you. Threading is STA. Here is an excert of the code that works
fine as a windows form... But, for some reason I can not put it together
to work as a service.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;
using Envox.ADXVoice;
using System.Data.SqlClient;
using System.Configuration;

namespace AnsweringSystem
{
public partial class Form1 : Form
{
private LineHandler[] LineArray;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
int iFromChannel = 0;
int iToChannel = 3; //4 channels

LineArray = new LineHandler[iToChannel - iFromChannel + 1];

for (int iChannel = iFromChannel; iChannel <= iToChannel;
iChannel++)
{
LineHandler Line = new LineHandler();
LineArray[iChannel - iFromChannel] = Line;
Line.iChannel = iChannel;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA);
wrkThread.Name = iChannel.ToString();
wrkThread.Start();
}
}

//Main class to handle individual channels on separate threads
private class LineHandler
{
public int iChannel = -1;
public Thread CurrentThread = null;

private ADXVoiceClass ADXVoice1 = null;

private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
try
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iChannel);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);
}
catch (COMException e)
{
ADXVoice1 = null;
return;
}
catch (Exception e)
{
ADXVoice1 = null;
return;
}

//Start message loop (keeps thread from exiting and allows
ADX to process events, including state changes)
Application.Run();

Marshal.ReleaseComObject(ADXVoice1); //make ADXVoice1
eligible for garbage collection
GC.Collect(); //force Garbage Collection
GC.WaitForPendingFinalizers(); //wait for completion
}

private void OnIncomingCall()
{
//code here to play prompts, branch to other methods, etc.
}

} //End LineHandler class

}
}
I very much appreciate any advice you may have. Thank you very much.

It looks like you are using an ActiveX Component, now AX was in general not
designed to be used from a service, make them work is in general a pain in
the a**, the problem is with the callbacks that arrive on anything but the
callers thread, that is they end on the thread pool threads which are MTA
and as such they need to be marshaled to the STA thread, that means you
need to pump Windows messages (not COM message), but services are not
designed to pump a message queue, only Windows applications are, you see the
dilemma?

I would suggest you to try to run this from a Console application first,
it's much easier to debug, and look how far you get before you drop this
into a service.

Willy.

May 16 '07 #9
Thanks Willy. I will try the console approach, however, still need to solve
the windows service dilema. For whatever reason the app runs perfectly as a
windows form but not as a windows service. And, when I remove
application.run from the windows form the app no longer runs. Any idea if
there is anything else I can try to get this functioning as a service?
Thank you very much. I really appreciate your help.

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:04**********************************@microsof t.com...
<msnews.microsoft.comwrote in message
news:Oi**************@TK2MSFTNGP03.phx.gbl...
>Thank you. Threading is STA. Here is an excert of the code that works
fine as a windows form... But, for some reason I can not put it together
to work as a service.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;
using Envox.ADXVoice;
using System.Data.SqlClient;
using System.Configuration;

namespace AnsweringSystem
{
public partial class Form1 : Form
{
private LineHandler[] LineArray;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
int iFromChannel = 0;
int iToChannel = 3; //4 channels

LineArray = new LineHandler[iToChannel - iFromChannel + 1];

for (int iChannel = iFromChannel; iChannel <= iToChannel;
iChannel++)
{
LineHandler Line = new LineHandler();
LineArray[iChannel - iFromChannel] = Line;
Line.iChannel = iChannel;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA);
wrkThread.Name = iChannel.ToString();
wrkThread.Start();
}
}

//Main class to handle individual channels on separate threads
private class LineHandler
{
public int iChannel = -1;
public Thread CurrentThread = null;

private ADXVoiceClass ADXVoice1 = null;

private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
try
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iChannel);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncom ingCall);
}
catch (COMException e)
{
ADXVoice1 = null;
return;
}
catch (Exception e)
{
ADXVoice1 = null;
return;
}

//Start message loop (keeps thread from exiting and allows
ADX to process events, including state changes)
Application.Run();

Marshal.ReleaseComObject(ADXVoice1); //make ADXVoice1
eligible for garbage collection
GC.Collect(); //force Garbage Collection
GC.WaitForPendingFinalizers(); //wait for completion
}

private void OnIncomingCall()
{
//code here to play prompts, branch to other methods, etc.
}

} //End LineHandler class

}
}
I very much appreciate any advice you may have. Thank you very much.


It looks like you are using an ActiveX Component, now AX was in general
not designed to be used from a service, make them work is in general a
pain in the a**, the problem is with the callbacks that arrive on anything
but the callers thread, that is they end on the thread pool threads which
are MTA and as such they need to be marshaled to the STA thread, that
means you need to pump Windows messages (not COM message), but services
are not designed to pump a message queue, only Windows applications are,
you see the dilemma?

I would suggest you to try to run this from a Console application first,
it's much easier to debug, and look how far you get before you drop this
into a service.

Willy.

May 16 '07 #10
What does the COM component do? Was it written in-house or is it an outside
product?

If in-house, obviously I'm going to ask if you can rewrite it in .NET. But
since that's probably not the case...what if you wrap the COM component in a
..NET console app, and call the .NET console app from your windows service?
I've never tried it...just an idea off the top of my head.

--
Brian Schwartz
FishNet Components
http://www.fishnetcomponents.com
Fish Grid .NET Light: Powerful Layouts for Small Datasets
<msnews.microsoft.comwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
Thanks Willy. I will try the console approach, however, still need to
solve the windows service dilema. For whatever reason the app runs
perfectly as a windows form but not as a windows service. And, when I
remove application.run from the windows form the app no longer runs. Any
idea if there is anything else I can try to get this functioning as a
service? Thank you very much. I really appreciate your help.

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:04**********************************@microsof t.com...
><msnews.microsoft.comwrote in message
news:Oi**************@TK2MSFTNGP03.phx.gbl...
>>Thank you. Threading is STA. Here is an excert of the code that works
fine as a windows form... But, for some reason I can not put it
together to work as a service.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;
using Envox.ADXVoice;
using System.Data.SqlClient;
using System.Configuration;

namespace AnsweringSystem
{
public partial class Form1 : Form
{
private LineHandler[] LineArray;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
int iFromChannel = 0;
int iToChannel = 3; //4 channels

LineArray = new LineHandler[iToChannel - iFromChannel + 1];

for (int iChannel = iFromChannel; iChannel <= iToChannel;
iChannel++)
{
LineHandler Line = new LineHandler();
LineArray[iChannel - iFromChannel] = Line;
Line.iChannel = iChannel;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA);
wrkThread.Name = iChannel.ToString();
wrkThread.Start();
}
}

//Main class to handle individual channels on separate threads
private class LineHandler
{
public int iChannel = -1;
public Thread CurrentThread = null;

private ADXVoiceClass ADXVoice1 = null;

private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
try
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iChannel);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnInco mingCall);
}
catch (COMException e)
{
ADXVoice1 = null;
return;
}
catch (Exception e)
{
ADXVoice1 = null;
return;
}

//Start message loop (keeps thread from exiting and allows
ADX to process events, including state changes)
Application.Run();

Marshal.ReleaseComObject(ADXVoice1); //make ADXVoice1
eligible for garbage collection
GC.Collect(); //force Garbage Collection
GC.WaitForPendingFinalizers(); //wait for completion
}

private void OnIncomingCall()
{
//code here to play prompts, branch to other methods, etc.
}

} //End LineHandler class

}
}
I very much appreciate any advice you may have. Thank you very much.


It looks like you are using an ActiveX Component, now AX was in general
not designed to be used from a service, make them work is in general a
pain in the a**, the problem is with the callbacks that arrive on
anything but the callers thread, that is they end on the thread pool
threads which are MTA and as such they need to be marshaled to the STA
thread, that means you need to pump Windows messages (not COM message),
but services are not designed to pump a message queue, only Windows
applications are, you see the dilemma?

I would suggest you to try to run this from a Console application first,
it's much easier to debug, and look how far you get before you drop this
into a service.

Willy.


May 16 '07 #11
Thanks a lot. It is a third party app that should be a .net component... I
make reference to it as a .net component in the .net tab in references.

"Brian Schwartz" <ow***@fishnetcomponentswos.comwrote in message
news:O4**************@TK2MSFTNGP03.phx.gbl...
What does the COM component do? Was it written in-house or is it an
outside product?

If in-house, obviously I'm going to ask if you can rewrite it in .NET. But
since that's probably not the case...what if you wrap the COM component in
a .NET console app, and call the .NET console app from your windows
service? I've never tried it...just an idea off the top of my head.

--
Brian Schwartz
FishNet Components
http://www.fishnetcomponents.com
Fish Grid .NET Light: Powerful Layouts for Small Datasets
<msnews.microsoft.comwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
>Thanks Willy. I will try the console approach, however, still need to
solve the windows service dilema. For whatever reason the app runs
perfectly as a windows form but not as a windows service. And, when I
remove application.run from the windows form the app no longer runs. Any
idea if there is anything else I can try to get this functioning as a
service? Thank you very much. I really appreciate your help.

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:04**********************************@microso ft.com...
>><msnews.microsoft.comwrote in message
news:Oi**************@TK2MSFTNGP03.phx.gbl...
Thank you. Threading is STA. Here is an excert of the code that works
fine as a windows form... But, for some reason I can not put it
together to work as a service.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;
using Envox.ADXVoice;
using System.Data.SqlClient;
using System.Configuration;

namespace AnsweringSystem
{
public partial class Form1 : Form
{
private LineHandler[] LineArray;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
int iFromChannel = 0;
int iToChannel = 3; //4 channels

LineArray = new LineHandler[iToChannel - iFromChannel + 1];

for (int iChannel = iFromChannel; iChannel <= iToChannel;
iChannel++)
{
LineHandler Line = new LineHandler();
LineArray[iChannel - iFromChannel] = Line;
Line.iChannel = iChannel;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA);
wrkThread.Name = iChannel.ToString();
wrkThread.Start();
}
}

//Main class to handle individual channels on separate threads
private class LineHandler
{
public int iChannel = -1;
public Thread CurrentThread = null;

private ADXVoiceClass ADXVoice1 = null;

private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
try
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iChannel);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnInc omingCall);
}
catch (COMException e)
{
ADXVoice1 = null;
return;
}
catch (Exception e)
{
ADXVoice1 = null;
return;
}

//Start message loop (keeps thread from exiting and
allows ADX to process events, including state changes)
Application.Run();

Marshal.ReleaseComObject(ADXVoice1); //make ADXVoice1
eligible for garbage collection
GC.Collect(); //force Garbage Collection
GC.WaitForPendingFinalizers(); //wait for completion
}

private void OnIncomingCall()
{
//code here to play prompts, branch to other methods, etc.
}

} //End LineHandler class

}
}
I very much appreciate any advice you may have. Thank you very much.

It looks like you are using an ActiveX Component, now AX was in general
not designed to be used from a service, make them work is in general a
pain in the a**, the problem is with the callbacks that arrive on
anything but the callers thread, that is they end on the thread pool
threads which are MTA and as such they need to be marshaled to the STA
thread, that means you need to pump Windows messages (not COM message),
but services are not designed to pump a message queue, only Windows
applications are, you see the dilemma?

I would suggest you to try to run this from a Console application first,
it's much easier to debug, and look how far you get before you drop this
into a service.

Willy.



May 16 '07 #12
It's got to be something with the way I'm threading because as soon as I
remove threading and only instantiate one adx object everything works fine.
Aby thoughts?
<msnews.microsoft.comwrote in message
news:Oe**************@TK2MSFTNGP06.phx.gbl...
Thanks a lot. It is a third party app that should be a .net component...
I make reference to it as a .net component in the .net tab in references.

"Brian Schwartz" <ow***@fishnetcomponentswos.comwrote in message
news:O4**************@TK2MSFTNGP03.phx.gbl...
>What does the COM component do? Was it written in-house or is it an
outside product?

If in-house, obviously I'm going to ask if you can rewrite it in .NET.
But since that's probably not the case...what if you wrap the COM
component in a .NET console app, and call the .NET console app from your
windows service? I've never tried it...just an idea off the top of my
head.

--
Brian Schwartz
FishNet Components
http://www.fishnetcomponents.com
Fish Grid .NET Light: Powerful Layouts for Small Datasets
<msnews.microsoft.comwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
>>Thanks Willy. I will try the console approach, however, still need to
solve the windows service dilema. For whatever reason the app runs
perfectly as a windows form but not as a windows service. And, when I
remove application.run from the windows form the app no longer runs.
Any idea if there is anything else I can try to get this functioning as
a service? Thank you very much. I really appreciate your help.

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:04**********************************@micros oft.com...
<msnews.microsoft.comwrote in message
news:Oi**************@TK2MSFTNGP03.phx.gbl...
Thank you. Threading is STA. Here is an excert of the code that
works fine as a windows form... But, for some reason I can not put it
together to work as a service.
>
>
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices;
using Envox.ADXVoice;
using System.Data.SqlClient;
using System.Configuration;
>
namespace AnsweringSystem
{
public partial class Form1 : Form
{
private LineHandler[] LineArray;
>
public Form1()
{
InitializeComponent();
}
>
private void Form1_Load(object sender, EventArgs e)
{
int iFromChannel = 0;
int iToChannel = 3; //4 channels
>
LineArray = new LineHandler[iToChannel - iFromChannel + 1];
>
for (int iChannel = iFromChannel; iChannel <= iToChannel;
iChannel++)
{
LineHandler Line = new LineHandler();
LineArray[iChannel - iFromChannel] = Line;
Line.iChannel = iChannel;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA);
wrkThread.Name = iChannel.ToString();
wrkThread.Start();
}
}
>
//Main class to handle individual channels on separate threads
private class LineHandler
{
public int iChannel = -1;
public Thread CurrentThread = null;
>
private ADXVoiceClass ADXVoice1 = null;
>
private delegate void TraceThreadSafe(string msg);
>
public void ProcessingThread()
{
try
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iChannel);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIn comingCall);
}
catch (COMException e)
{
ADXVoice1 = null;
return;
}
catch (Exception e)
{
ADXVoice1 = null;
return;
}
>
//Start message loop (keeps thread from exiting and
allows ADX to process events, including state changes)
Application.Run();
>
Marshal.ReleaseComObject(ADXVoice1); //make ADXVoice1
eligible for garbage collection
GC.Collect(); //force Garbage Collection
GC.WaitForPendingFinalizers(); //wait for completion
}
>
private void OnIncomingCall()
{
//code here to play prompts, branch to other methods, etc.
}
>
} //End LineHandler class
>
}
}
>
>
I very much appreciate any advice you may have. Thank you very much.
>
It looks like you are using an ActiveX Component, now AX was in general
not designed to be used from a service, make them work is in general a
pain in the a**, the problem is with the callbacks that arrive on
anything but the callers thread, that is they end on the thread pool
threads which are MTA and as such they need to be marshaled to the STA
thread, that means you need to pump Windows messages (not COM
message), but services are not designed to pump a message queue, only
Windows applications are, you see the dilemma?

I would suggest you to try to run this from a Console application
first, it's much easier to debug, and look how far you get before you
drop this into a service.

Willy.



May 16 '07 #13
<msnews.microsoft.comwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
Thanks Willy. I will try the console approach, however, still need to
solve the windows service dilema. For whatever reason the app runs
perfectly as a windows form but not as a windows service. And, when I
remove application.run from the windows form the app no longer runs. Any
idea if there is anything else I can try to get this functioning as a
service? Thank you very much. I really appreciate your help.
Well, it runs from a Windows.Forms application because this is the normal
habitat for AX controls, they run in an STA thread that pumps the windows
message queue. So, the only way to make it work (be it unreliable) is to
make your service a Windows application, that is, create a context with a
form and run the message pump by a call to Application.Run, but beware that
you need to handle a lot of interactions with the windows system (handle
Windows events like Close etc...), and you'll need to find a way to interact
with the COM object too. Note that such scenario is not supported, it's
really a bad idea to try to run AX in Windows Services, it will break sooner
than later ....

Willy.

May 16 '07 #14
<msnews.microsoft.comwrote in message
news:Oe**************@TK2MSFTNGP06.phx.gbl...
Thanks a lot. It is a third party app that should be a .net component...
I make reference to it as a .net component in the .net tab in references.

Wait a minute, if you set a reference to a ".NET component", it means it's a
".NET component" and NOT a COM object, so you may forget all what's been
said about COM, STA's and message queues. So again, may I ask you what you
mean by "it doesn't work", and as I said in another reply, try first to make
it work from a simple Console Application.

Willy.
May 16 '07 #15
<msnews.microsoft.comwrote in message
news:%2******************@TK2MSFTNGP02.phx.gbl...
It's got to be something with the way I'm threading because as soon as I
remove threading and only instantiate one adx object everything works
fine. Aby thoughts?

What do you mean by "the way you are threading" and "remove threading"?
Are you sure the third party .NET class doesn't call into COM, that is, are
you sure it's not a simple COM wrapper.

Willy.

May 16 '07 #16

<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
>I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM component
I a using in the app (required for message loop). I have created a windows
service from VStudio 2005 template. What is the windows service
replacement for Application.Run()?

Create a thread to host your objects (not the main service thread which must
be controlled by the SCM).

In this thread, spend most of your time in a classic
PeekMessage/DispatchMessage loop, so COM marshalling works as expected.
May 17 '07 #17
Watching the Output window I'm noticing that without Application.Run in my
windows form app that the message loop doesnt start so the threads exit and
the .net component cant process events. Same thing with the windows
service. All is well in the windows form app with application.run. How can
i simulate this same application.run functionality in a windows service? I
very much appreciate all of your help. Thank you.
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:e9**************@TK2MSFTNGP02.phx.gbl...
>
<msnews.microsoft.comwrote in message
news:Oc*************@TK2MSFTNGP06.phx.gbl...
>>I have a multi threaded windows form application that runs great after
calling Application.Run(). Application.Run is required for a COM
component I a using in the app (required for message loop). I have
created a windows service from VStudio 2005 template. What is the windows
service replacement for Application.Run()?


Create a thread to host your objects (not the main service thread which
must be controlled by the SCM).

In this thread, spend most of your time in a classic
PeekMessage/DispatchMessage loop, so COM marshalling works as expected.

May 17 '07 #18
<msnews.microsoft.comwrote in message
news:uf**************@TK2MSFTNGP06.phx.gbl...
Watching the Output window I'm noticing that without Application.Run in my
windows form app that the message loop doesnt start so the threads exit
and the .net component cant process events. Same thing with the windows
service. All is well in the windows form app with application.run. How
can i simulate this same application.run functionality in a windows
service? I very much appreciate all of your help. Thank you.

Again, are you talking about a COM object or are you talking about a .NET
component, I'm asking this because in another reply you said that you were
adding a reference to a ".NET component" , and I replied by saying that a
..NET components is not a COM component.
Anyway, if it's a .NET component , it looks like it depends on
Windows.Forms, and this is a big no no in Windows Services, the
documentation states that it's not a supported scenario. If however you
don't care about all these warnings, just go ahaed, make your service a UI
styale application, by adding a reference to Windows.Forms, create a Form as
you did your Windows appliaction and set the Windows Service property
"Interact with the Desktop" to true and set the Identity of the Service
account to SYSTEM. But I warned you, you will end in a world of pain.

Willy.

May 17 '07 #19

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:8D**********************************@microsof t.com...
<msnews.microsoft.comwrote in message
news:uf**************@TK2MSFTNGP06.phx.gbl...
>Watching the Output window I'm noticing that without Application.Run in
my windows form app that the message loop doesnt start so the threads
exit and the .net component cant process events. Same thing with the
windows service. All is well in the windows form app with
application.run. How can i simulate this same application.run
functionality in a windows service? I very much appreciate all of your
help. Thank you.


Again, are you talking about a COM object or are you talking about a .NET
component, I'm asking this because in another reply you said that you were
adding a reference to a ".NET component" , and I replied by saying that a
.NET components is not a COM component.
Anyway, if it's a .NET component , it looks like it depends on
Windows.Forms, and this is a big no no in Windows Services, the
documentation states that it's not a supported scenario. If however you
don't care about all these warnings, just go ahaed, make your service a UI
styale application, by adding a reference to Windows.Forms, create a Form
as you did your Windows appliaction and set the Windows Service property
"Interact with the Desktop" to true and set the Identity of the Service
no, don't enable "Interact with Desktop". That isn't needed for processing
the message queue, and is a very bad idea, not to mention no longer allowed
in Vista.
account to SYSTEM. But I warned you, you will end in a world of pain.

Willy.

May 17 '07 #20
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:uv**************@TK2MSFTNGP02.phx.gbl...
>
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:8D**********************************@microsof t.com...
><msnews.microsoft.comwrote in message
news:uf**************@TK2MSFTNGP06.phx.gbl...
>>Watching the Output window I'm noticing that without Application.Run in
my windows form app that the message loop doesnt start so the threads
exit and the .net component cant process events. Same thing with the
windows service. All is well in the windows form app with
application.run. How can i simulate this same application.run
functionality in a windows service? I very much appreciate all of your
help. Thank you.


Again, are you talking about a COM object or are you talking about a .NET
component, I'm asking this because in another reply you said that you
were adding a reference to a ".NET component" , and I replied by saying
that a .NET components is not a COM component.
Anyway, if it's a .NET component , it looks like it depends on
Windows.Forms, and this is a big no no in Windows Services, the
documentation states that it's not a supported scenario. If however you
don't care about all these warnings, just go ahaed, make your service a
UI styale application, by adding a reference to Windows.Forms, create a
Form as you did your Windows appliaction and set the Windows Service
property "Interact with the Desktop" to true and set the Identity of the
Service

no, don't enable "Interact with Desktop". That isn't needed for
processing the message queue, and is a very bad idea, not to mention no
longer allowed in Vista.
>account to SYSTEM. But I warned you, you will end in a world of pain.

Willy.


Agreed, this was only to make it easier for the OP to debug, once he got it
running he could reset this attribute.
It's a very bad idea to have Windows.Forms in Services in the first place,
it's clear that the OP is trying to use a .NET component that has a
dependency on Windows.Forms, (why, is just something the OP is not able to
answer I'm afraid).
It looks like this component needs a Window host (a HWND), maybe it creates
some hidden window or worse has a UI (a tray ICON or whatever), I really
wonder what kind component it is!
Note that you can still interact with the desktop in Vista, be it as an
interim solution for backward compatibility reasons :-(, anyway, Services on
Vista should not run Windows message loops either, everything that needs a
message loop doesn't belong in a Service.

Willy.

May 17 '07 #21
Thanks Willy. I have confirmed that it is a .net component. The component
does function when inside a windows service,however, not when multi
threading is involved.
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:8D**********************************@microsof t.com...
<msnews.microsoft.comwrote in message
news:uf**************@TK2MSFTNGP06.phx.gbl...
>Watching the Output window I'm noticing that without Application.Run in
my windows form app that the message loop doesnt start so the threads
exit and the .net component cant process events. Same thing with the
windows service. All is well in the windows form app with
application.run. How can i simulate this same application.run
functionality in a windows service? I very much appreciate all of your
help. Thank you.


Again, are you talking about a COM object or are you talking about a .NET
component, I'm asking this because in another reply you said that you were
adding a reference to a ".NET component" , and I replied by saying that a
.NET components is not a COM component.
Anyway, if it's a .NET component , it looks like it depends on
Windows.Forms, and this is a big no no in Windows Services, the
documentation states that it's not a supported scenario. If however you
don't care about all these warnings, just go ahaed, make your service a UI
styale application, by adding a reference to Windows.Forms, create a Form
as you did your Windows appliaction and set the Windows Service property
"Interact with the Desktop" to true and set the Identity of the Service
account to SYSTEM. But I warned you, you will end in a world of pain.

Willy.

May 18 '07 #22
<msnews.microsoft.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
Thanks Willy. I have confirmed that it is a .net component. The
component does function when inside a windows service,however, not when
multi threading is involved.
Please be more specific,
do you mean it's working from a single thread when running in a Service
process AND this without the need for Windows.Forms?
Is this a pure managed component, or does it have dependencies on other non
managed components like COM?
What kind of component is this and what's his role?
Is this components set documented, what does it say about threading?
What is do you mean with " it's not working when multiple threads are
involved"?
Did you try from a console application and noticed the same behavior? If you
did can you post the console apps. code?

Willy.

May 18 '07 #23
Thank you Willy for all of the assistance. I very much appreciate it. I've
been having a hell of a time with this.

Here is Windows Service (no threading) code that does work fine. The Envox
..net component answers OnIncomingCall. Everrything works fine with this
code...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using Envox.ADXVoice;

namespace WindowsService3
{
public partial class Service1 : ServiceBase
{
private ADXVoiceClass ADXVoice1 = null;

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(0);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);
}

private void OnIncomingCall()
{
try
{
ADXVoice1.ClearDigits();
ADXVoice1.AnswerCall();
Play_Welcome_Message();
}
finally
{
if (ADXVoice1.TrunkState != DEV_STATE.DEV_STATE_Idle)
{
ADXVoice1.DisconnectCall();
}
}
}

private void Play_Welcome_Message()
{
ADXVoice1.PlayFile(@"e:\voxfiles\144.vox", null, "+", null,
null);
ADXVoice1.PlayFile(@"e:\voxfiles\145.vox", null, "+", null,
null);
}

protected override void OnStop()
{
}
}
}

Here is my multithreaded Windows Service code that does not work
(onincomingcall never executes). I require the 4 threads for the Envox .net
component to listen and answer calls on 4 different lines. This code does
not work for some reason...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using Envox.ADXVoice;

namespace WindowsService4
{
public partial class Service1 : ServiceBase
{
private LineHandler[] LineArray;

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
StartApp();
}

private void StartApp()
{
int iFromTrunk = 0;
int iToTrunk = 14;

LineArray = new LineHandler[iToTrunk - iFromTrunk + 1];

for (int iTrunk = iFromTrunk; iTrunk <= iToTrunk; iTrunk++)
{
LineHandler Line = new LineHandler();
LineArray[iTrunk - iFromTrunk] = Line;
Line.iTrunk = iTrunk;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA); //default is
MTA
wrkThread.Name = iTrunk.ToString();
wrkThread.Start();
}
}

protected override void OnStop()
{
}

private class LineHandler
{
public int iTrunk = -1;
public Thread CurrentThread = null;
private ADXVoiceClass ADXVoice1 = null;
private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
int iThreadId = CurrentThread.GetHashCode();

ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iTrunk);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);

//Start message loop (keeps thread from exiting and allows
Envox .net component to process events, including state changes)
//Windows service aternate to application.run required
here...
//Application.Run();
}

private void OnIncomingCall()
{
try
{
ADXVoice1.ClearDigits();
ADXVoice1.AnswerCall();
Play_Welcome_Message();
}
finally
{
if (ADXVoice1.TrunkState != DEV_STATE.DEV_STATE_Idle)
{
ADXVoice1.DisconnectCall();
}
}
}

private void Play_Welcome_Message()
{
ADXVoice1.PlayFile(@"e:\voxfiles\144.vox", null, "+", null,
null);
ADXVoice1.PlayFile(@"e:\voxfiles\145.vox", null, "+", null,
null);
}
}
}
}
The above code, however, does function as a windows form whe using
paplication.run. I'd very much appreciate you comments or advice. Thank
you very much.

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:5E**********************************@microsof t.com...
<msnews.microsoft.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
>Thanks Willy. I have confirmed that it is a .net component. The
component does function when inside a windows service,however, not when
multi threading is involved.

Please be more specific,
do you mean it's working from a single thread when running in a Service
process AND this without the need for Windows.Forms?
Is this a pure managed component, or does it have dependencies on other
non managed components like COM?
What kind of component is this and what's his role?
Is this components set documented, what does it say about threading?
What is do you mean with " it's not working when multiple threads are
involved"?
Did you try from a console application and noticed the same behavior? If
you did can you post the console apps. code?

Willy.

May 18 '07 #24
<msnews.microsoft.comwrote in message
news:Os**************@TK2MSFTNGP03.phx.gbl...
Thank you Willy for all of the assistance. I very much appreciate it.
I've been having a hell of a time with this.

Here is Windows Service (no threading) code that does work fine. The
Envox .net component answers OnIncomingCall. Everrything works fine with
this code...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using Envox.ADXVoice;

namespace WindowsService3
{
public partial class Service1 : ServiceBase
{
private ADXVoiceClass ADXVoice1 = null;

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(0);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);
}

private void OnIncomingCall()
{
try
{
ADXVoice1.ClearDigits();
ADXVoice1.AnswerCall();
Play_Welcome_Message();
}
finally
{
if (ADXVoice1.TrunkState != DEV_STATE.DEV_STATE_Idle)
{
ADXVoice1.DisconnectCall();
}
}
}

private void Play_Welcome_Message()
{
ADXVoice1.PlayFile(@"e:\voxfiles\144.vox", null, "+", null,
null);
ADXVoice1.PlayFile(@"e:\voxfiles\145.vox", null, "+", null,
null);
}

protected override void OnStop()
{
}
}
}

Here is my multithreaded Windows Service code that does not work
(onincomingcall never executes). I require the 4 threads for the Envox
.net component to listen and answer calls on 4 different lines. This code
does not work for some reason...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using Envox.ADXVoice;

namespace WindowsService4
{
public partial class Service1 : ServiceBase
{
private LineHandler[] LineArray;

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
StartApp();
}

private void StartApp()
{
int iFromTrunk = 0;
int iToTrunk = 14;

LineArray = new LineHandler[iToTrunk - iFromTrunk + 1];

for (int iTrunk = iFromTrunk; iTrunk <= iToTrunk; iTrunk++)
{
LineHandler Line = new LineHandler();
LineArray[iTrunk - iFromTrunk] = Line;
Line.iTrunk = iTrunk;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA); //default
is MTA
wrkThread.Name = iTrunk.ToString();
wrkThread.Start();
}
}

protected override void OnStop()
{
}

private class LineHandler
{
public int iTrunk = -1;
public Thread CurrentThread = null;
private ADXVoiceClass ADXVoice1 = null;
private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
int iThreadId = CurrentThread.GetHashCode();

ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iTrunk);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);

//Start message loop (keeps thread from exiting and allows
Envox .net component to process events, including state changes)
//Windows service aternate to application.run required
here...
//Application.Run();
}

private void OnIncomingCall()
{
try
{
ADXVoice1.ClearDigits();
ADXVoice1.AnswerCall();
Play_Welcome_Message();
}
finally
{
if (ADXVoice1.TrunkState != DEV_STATE.DEV_STATE_Idle)
{
ADXVoice1.DisconnectCall();
}
}
}

private void Play_Welcome_Message()
{
ADXVoice1.PlayFile(@"e:\voxfiles\144.vox", null, "+", null,
null);
ADXVoice1.PlayFile(@"e:\voxfiles\145.vox", null, "+", null,
null);
}
}
}
}
The above code, however, does function as a windows form whe using
paplication.run. I'd very much appreciate you comments or advice. Thank
you very much.


Sorry ,but I can't help you out if you don't answer my questions (see my
previous reply), also I didn't ask to post the service code, I asked for a
Console application. Anyway, as I said before, I'm pretty sure this .NET
component (if it's really not a AX Control) is hiding an unmanaged component
(guess, a COM ActiveX control from Envox), so again check this! Ask the
implementer of the .NET component, if you are not able to find this out
yourself. I can't possibly know what the NET wrapper (if any) is doing at
the thread level, whether it creates forms or not, the same is true for the
underlying control. All I can say is that if it's an AX control, forget it
to make it work from a Service, If you don't believe me , ask Envox whether
they support this to be run in a Windows Service, the answer will be NO.
One last question though, why do you want it to be run from a Service, why
can't you run it from a Windows application?

Willy.

May 18 '07 #25
<msnews.microsoft.comwrote in message
news:Os**************@TK2MSFTNGP03.phx.gbl...
Thank you Willy for all of the assistance. I very much appreciate it.
I've been having a hell of a time with this.

Here is Windows Service (no threading) code that does work fine. The
Envox .net component answers OnIncomingCall. Everrything works fine with
this code...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using Envox.ADXVoice;

namespace WindowsService3
{
public partial class Service1 : ServiceBase
{
private ADXVoiceClass ADXVoice1 = null;

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(0);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);
}

private void OnIncomingCall()
{
try
{
ADXVoice1.ClearDigits();
ADXVoice1.AnswerCall();
Play_Welcome_Message();
}
finally
{
if (ADXVoice1.TrunkState != DEV_STATE.DEV_STATE_Idle)
{
ADXVoice1.DisconnectCall();
}
}
}

private void Play_Welcome_Message()
{
ADXVoice1.PlayFile(@"e:\voxfiles\144.vox", null, "+", null,
null);
ADXVoice1.PlayFile(@"e:\voxfiles\145.vox", null, "+", null,
null);
}

protected override void OnStop()
{
}
}
}

Here is my multithreaded Windows Service code that does not work
(onincomingcall never executes). I require the 4 threads for the Envox
.net component to listen and answer calls on 4 different lines. This code
does not work for some reason...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using Envox.ADXVoice;

namespace WindowsService4
{
public partial class Service1 : ServiceBase
{
private LineHandler[] LineArray;

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
StartApp();
}

private void StartApp()
{
int iFromTrunk = 0;
int iToTrunk = 14;

LineArray = new LineHandler[iToTrunk - iFromTrunk + 1];

for (int iTrunk = iFromTrunk; iTrunk <= iToTrunk; iTrunk++)
{
LineHandler Line = new LineHandler();
LineArray[iTrunk - iFromTrunk] = Line;
Line.iTrunk = iTrunk;
ThreadStart ts = new ThreadStart(Line.ProcessingThread);
Thread wrkThread = new Thread(ts);
Line.CurrentThread = wrkThread;
wrkThread.SetApartmentState(ApartmentState.STA); //default
is MTA
wrkThread.Name = iTrunk.ToString();
wrkThread.Start();
}
}

protected override void OnStop()
{
}

private class LineHandler
{
public int iTrunk = -1;
public Thread CurrentThread = null;
private ADXVoiceClass ADXVoice1 = null;
private delegate void TraceThreadSafe(string msg);

public void ProcessingThread()
{
int iThreadId = CurrentThread.GetHashCode();

ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iTrunk);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);

//Start message loop (keeps thread from exiting and allows
Envox .net component to process events, including state changes)
//Windows service aternate to application.run required
here...
//Application.Run();
}

private void OnIncomingCall()
{
try
{
ADXVoice1.ClearDigits();
ADXVoice1.AnswerCall();
Play_Welcome_Message();
}
finally
{
if (ADXVoice1.TrunkState != DEV_STATE.DEV_STATE_Idle)
{
ADXVoice1.DisconnectCall();
}
}
}

private void Play_Welcome_Message()
{
ADXVoice1.PlayFile(@"e:\voxfiles\144.vox", null, "+", null,
null);
ADXVoice1.PlayFile(@"e:\voxfiles\145.vox", null, "+", null,
null);
}
}
}
}
The above code, however, does function as a windows form whe using
paplication.run. I'd very much appreciate you comments or advice. Thank
you very much.

I took a quick look at your code (the second case), and found that you don't
keep your threads running at all, all you are doing is create an instance of
ADXVoiceClass add an eventhandler and return from your thread procedure,
that means that the thread will most probably get collected at the next GC
run. That means that basically you don't have any of your 15 threads running
( that is pumping messages). At least you need to keep the thread running
and pump the queue (again STA threads need to pump the queue!!), for COM
messages only, you can do this by means of a pumping wait like :
public void ProcessingThread()
{
....
// pump COM messages once per second, in an endless loop!!
while(!Thread.CurrentThread.Join(new TimeSpan(0,0,1)));
}

for Windows messages you need Application.Run().

Willy.


May 18 '07 #26
<msnews.microsoft.comwrote in message
news:Os**************@TK2MSFTNGP03.phx.gbl...
ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iTrunk);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncomi ngCall);
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[i] = new ManualResetEvent(false);
t[i] = new Thread(new
ParameterizedThreadStart(ProcessingThread),200000) ;
t[i].SetApartmentState(ApartmentState.STA);
t[i].IsBackground=true;
t[i].Start(mre[i]);
}

public void ProcessingThread(object shutdownEvent)
{
....
ADXVoice1.InCommingCall += new
_IADXVoiceEvents_InCommingCallEventHandler(OnIncom ingCall);
// 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(OnIncom ingCall);
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.


May 20 '07 #27
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 [MVP]" <wi*************@telenet.bewrote in message
news:CF**********************************@microsof t.com...
<msnews.microsoft.comwrote in message
news:Os**************@TK2MSFTNGP03.phx.gbl...
> ADXVoice1 = new ADXVoiceClass();
ADXVoice1.TrunkAssign(iTrunk);
ADXVoice1.IncomingCall += new
_IADXVoiceEvents_IncomingCallEventHandler(OnIncom ingCall);

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[i] = new ManualResetEvent(false);
t[i] = new Thread(new
ParameterizedThreadStart(ProcessingThread),200000) ;
t[i].SetApartmentState(ApartmentState.STA);
t[i].IsBackground=true;
t[i].Start(mre[i]);
}

public void ProcessingThread(object shutdownEvent)
{
....
ADXVoice1.InCommingCall += new
_IADXVoiceEvents_InCommingCallEventHandler(OnIncom ingCall);
// 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(OnIncom ingCall);
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.


May 22 '07 #28
<msnews.microsoft.comwrote in message
news:%2****************@TK2MSFTNGP06.phx.gbl...
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.
Weird, If it works in a Forms application using multiple threads, it should
also work from a service, provided things are initialized correctly.
I would try to make it run from a console application, if this works, you
can schedule this application to start at boot time using the system
scheduler.

Willy.
May 22 '07 #29

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by CodeMonkey | last post: by
6 posts views Thread by kumar_anil_gaya_India | last post: by
2 posts views Thread by =?Utf-8?B?dmlzaHJ1dGg=?= | last post: by
1 post views Thread by =?Utf-8?B?dmlzaHJ1dGg=?= | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.