1

I have a console application, in which I have a connection to a third party windows service on a remote server by tcp/ip.

The call Hierarchy likes:

static class Program
{
    [MTAThread]
    static void Main()
    {
        MyApplication.Start();

The Start method

public static void Start()
{
    lock (SyncVar)
    {
        ThreadStart ts = new ThreadStart(MainCode);
        MainCodeThread = new Thread(ts);
        MainCodeThread.IsBackground = false;
        MainCodeThread.Start();

The detail of main thread has:

private static void MainCode()
{
    try
    {
         // connect to the remote server, against a windows service 
         TelephonyServer tServer = new TelephonyServer(sIpaddress, "username", "password");
         while (true)
         {
            Task consumer = Task.Run(() =>
             {
                   if (data != "")
                   {
                        ProcessEachChannel(data);
            });

            Task producer = Task.Run(() =>
            {
                // blah blah
            });

In the method ProcessEachChannel, we have

    public bool ProcessEachChannel(string workItem)
    {
        ChannelResource cr = tServer.GetChannel();
        // blah blah
    }

Now the application is working well. However if I click the red exit cross of the application or click stop debugging button from Visual Studio, the resources ChannelResource cr is not destroyed at all. I found the fact from the remote server service control dashboard.

I tried some code

System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess(); process.Exited += new EventHandler(OnExited);

It is not helpful. I heard some tricks to manage the thread by passing parameters to the main thread then set something true or false etc but just no clue.

  • A .NET application gets cleaned up on appdomain teardown, i.e. when your console application exits. Either the `TelephonyServer.GetChannel` leaks something somehow, or the service control dashboard simply hasn't detected yet that the console app is no longer connected. We cannot analyze this issue from the information given. – CodeCaster Aug 18 '14 at 18:18
  • 1
    Have you looked at this: http://stackoverflow.com/a/1119869/2638872? You could add (and be sure to remove) a handler for the `processExit` event in `ProcessEachChannel` with a lambda that disposes the object properly. – mrtig Aug 18 '14 at 18:19
  • It is a telephony application. When the application shut down, the port or channel is still occupied. It is suppose to be idle. –  Aug 18 '14 at 18:21

2 Answers2

1

The program will not exit until all running threads have been stopped.

Replace the while (true) in the thread code with while (!stopThread.WaitOne(10, false)) where stopThread is a WaitHandle like ManualResetEvent.

Then, when the application shuts down, Set the event and wait for the thread to exit.

Also note that some 3rd-party frameworks depend on Dispose being called on their object because they need to manage the lifetime of some separate threads they've spawned. F.e. read VoiceElements document and see how they call Disconnect and Dispose on a ChannelResource they've got from GetChannel(). Please check with the provider when and where you need to release used resources yourself.

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
  • Actually I have the code `while (true) { ThreadEvent.WaitOne(waitingTime, false);` I just omitted in the question. –  Aug 18 '14 at 18:26
  • Ok so you still need to add a WaitHandle so you can exit the thread. And since you have 2 WaitHandles than, you'll need [`WaitHanle.WaitAny`](http://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitany(v=vs.110).aspx) method and wait until one of the events is set, then act accordingly. – huysentruitw Aug 18 '14 at 18:27
  • I just worry even I have a WaitHandle, the program doesn't reach it when I click the red exit cross. The whole window closed. –  Aug 18 '14 at 18:44
  • Then I'm afraid we do not have enough information to help you with this issue since `TelephonyServer` doesn't look like any public API according to Dr.Google – huysentruitw Aug 18 '14 at 18:51
  • Here is some information. http://www.voiceelements.com/documentation/gettingstarted/ –  Aug 18 '14 at 18:54
  • Yes, already checked the demo project at http://support.voiceelements.com/index.php?title=Voice_Elements_Skeleton_Project_-_C#_VS2005 and I see that they're calling `Dispose` on the ChannelResource things, so you might have forgotten this in your code. – huysentruitw Aug 18 '14 at 18:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59529/discussion-between-love-and-wouter-huysentruit). –  Aug 18 '14 at 18:57
0

If you kill the process, instead of closing it gracefully (and that is what you do when you close the console window or press the stop buttpn in debugger), there's no chance for any cleanup code to run. you have to implement some exit handler, perhaps catching a ctrl-c press and then return from your threads, so all objects can cleanly dispose themselves.

ths
  • 2,858
  • 1
  • 16
  • 21
  • The difficult thing is that I want to press the stop button in debugger directly rather than ctrl-c. Can we use a child thread to fulfill my purpose? –  Aug 21 '14 at 13:06
  • No. if you press stop, *no* code of your program can run anymore. that's the function of the stop button. – ths Aug 21 '14 at 16:03
  • You are right. My boss insisted me to close the app but I think that he misunderstood the question. The application is a console application. He thought it was a windows form app therefore there was a closing event code could handle it. Sign... –  Aug 21 '14 at 20:26