0

I'm stuck again and hope someone can help me. This is the code I have so far and I don't know why Program.RunServerTask.Wait() never unblocks after the ExitToolStripMenuItem_Click method runs. I was under the impression that if the task completes, the wait finishes and would resume the Application.Exit() method. But I am obviously wrong, what am I missing here? Thanks.

internal static class Program {
    internal static Task RunServerTask;
    private static LicenseManagerForm _licenseManagerForm;

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

        RunServerTask = Task.Run(ServerStream.RunServerAsync);

        _licenseManagerForm = new LicenseManagerForm();
        Application.Run(_licenseManagerForm);
    }
}

internal static class ServerStream {
    internal static async Task RunServerAsync() {
        // 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 GetTcpClientAsync(serverSocket, _cancellationTokenSource.Token);
            }
            catch (Exception e) {
                _ = MessageBox.Show(e.ToString());
                throw;
            }
        }
    }

    private static async Task<TcpClient> GetTcpClientAsync(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();
    }
}

public partial class LicenseManagerForm : Form {
    public LicenseManagerForm() {
        InitializeComponent();
    }

    private void LicenseManagerForm_FormClosing(object sender, FormClosingEventArgs e) {
        e.Cancel = true;
        WindowState = FormWindowState.Minimized;
        ShowInTaskbar = false;
        Hide();
        NotifyIcon.Visible = true;
    }

    private void LicenseManagerForm_Resize(object sender, EventArgs e) {
        if (WindowState != FormWindowState.Minimized) return;

        Hide();
        NotifyIcon.Visible = true;
    }

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

        Program.RunServerTask.Wait();
        Application.Exit();
    }
}
Jeffrey
  • 528
  • 5
  • 14
  • 1
    You've deadlocked the UI thread. See duplicate. You should use `await Program.RunServerTask;` instead. – Peter Duniho Mar 06 '21 at 02:13
  • Ok, but still brings me back to the problem I had yesterday, where the application isn't exiting on the Application.Exit() method. – Jeffrey Mar 06 '21 at 03:14
  • Never mind, I thought Application.Exit() bypassed the FormClosing event, I need to read better. – Jeffrey Mar 06 '21 at 03:30
  • _"still brings me back to the problem I had yesterday"_ -- How does it do that? Do you understand that the process won't exit _exactly_ when you make that call, but rather after the message queue for the thread has been emptied? – Peter Duniho Mar 06 '21 at 03:30

0 Answers0