0

I'm running a winform application that uses a contextMenuStrip on a notifyIcon to exit the application. The exit function stops another thread that is running, turns off the Icon visibility, and then exits the application. For some reason though I have to call Application.Exit() twice to exit the application. I searched through all of my code and didn't find another Application.Run() call, so I'm not sure what would be causing this.

These are the primary methods that are running:

    private static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Thread socketThread = new Thread(ServerStream.RunServer);
        socketThread.Start();

        Application.Run(new LicenseManagerForm());
    }

    private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
    {
        ServerStream.StopListenerTask();
        NotifyIcon.Visible = false;
        Application.Exit();
        Application.Exit();
    }

    internal static async void RunServer()
    {
        // Create an IPv4 TCP/IP socket.
        TcpListener serverSocket = new TcpListener(IPAddress.Any, 11000);

        // Listen for incoming connections.
        serverSocket.Start();

        while (!_stopServer)
        {
            try
            {
                TcpClient clientRequest = await GetTcpClient(serverSocket, _cancellationTokenSource.Token);
                if (clientRequest != null) AuthenticateClient(clientRequest);
            }
            catch (Exception e)
            {
                //Program.WriteTextToStatusBar(e.ToString());
                _ = MessageBox.Show(e.ToString());
                throw;
            }
        }
    }

    private static async Task<TcpClient> GetTcpClient(TcpListener listener, CancellationToken token)
    {
        _ = token.Register(listener.Stop);

        try
        {
            return await listener.AcceptTcpClientAsync().ConfigureAwait(false);
        }
        catch (ObjectDisposedException)
        {
            if (token.IsCancellationRequested) return null;
            throw;
        }
    }

    internal static void StopListenerTask()
    {
        _stopServer = true;
        _cancellationTokenSource.Cancel();
    }

Is there anything here that would cause the first Application.Exit() to fail?

Jeffrey
  • 528
  • 5
  • 14
  • Also check https://stackoverflow.com/questions/8507978/exiting-a-c-sharp-winforms-application – Progman Mar 04 '21 at 20:05
  • 1
    Calling `Application.Exit()` doesn't do anything except introduce a delay to allow more time for the foreground thread running the server to exit. See duplicate for the details you need to understand the differing behaviors of the different techniques for closing a process. It's not strictly necessary, but if you want a more ordered shutdown, you can fix your server so that it returns a proper `Task` and then await it before actually calling `Exit()`. – Peter Duniho Mar 04 '21 at 20:16
  • 1
    I'll also point out that creating an explicit thread for the purpose of the `RunServer()` method is pointless. At the first `await`, the thread you start exits, and when the method is resumed, execution happens on a thread pool thread. You might as well just call the method directly. – Peter Duniho Mar 04 '21 at 20:18
  • @PeterDuniho Ah, I was thinking that since Application.Exit() would have to wait for the StopListenerTask() to finish, that the RunServer() thread would be cancelled and finished. It didn't dawn on me that StopListenerTask() doesn't actually care if RunServer() has finished cancelling or not. – Jeffrey Mar 04 '21 at 20:54

0 Answers0