3
votes

I have made an application to fetch data from client using asynchronous socket programming. The user can see the application as a icon in tasktray and can 'close' the application by using right click menu on the tray icon. To do this I wrote a Windows forms application, made form invisible, associated a notifyicon which is visible always. In the notifyicon added a contextmenu and display a 'close' option as a contextmenu menuitem to the user.

The contextmenu is displayed fine on right click on the tray icon. But when menuitem of the contextmenu is clicked, the application does not close as coded. It requires one more right click on the tray icon (after clicking the close option), which then closes all the resources. Please find the relevant code as under-

public partial class Form1 : Form
{
    private ContextMenu m_menu;
    public static ManualResetEvent allDone = new ManualResetEvent(false);
    public Form1()
    {
        InitializeComponent();
        m_menu = new ContextMenu();
        m_menu.MenuItems.Add(0, new MenuItem("Close", new System.EventHandler(menuItem1_Click)));
        notifyIcon1.ContextMenu =this.m_menu;
        notifyIcon1.DoubleClick += new System.EventHandler(this.notifyIcon1_DoubleClick);
        // Initiate listening for sockets
        StartListening();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    // State object for reading client data asynchronously
    public class StateObject
    {
        // Client socket, size of receive buffer, receive buffer and received data string.
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }

    // socket program goes here, with msdn AcceptCallback and ReceiveCallback

    public static void StartListening()
    {              // Create a TCP/IP socket.
            string port = ConfigurationManager.AppSettings["port"];
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Convert.ToInt32(port));
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and listen for incoming connections.
        try
            {
                listener.Bind(localEndPoint);
                listener.Listen(1);

            while (true)
                {
                    // Set the event to nonsignaled state.
                    allDone.Reset();
                    // Start an asynchronous socket to listen for connections.
                    listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
                    // Wait until a connection is made before continuing.
                    allDone.WaitOne();
                }
            }
            catch (Exception ex)
            {
        }
    }

        // AsyncResult tells status of asynchronous operation
    private static void AcceptCallback(IAsyncResult AR)
    {
            // Signal the main thread to continue.
            allDone.Set();
            // handler is the socket to accept incoming connection and create socket to handle remote host communications
            // Get the socket that handles the client request.
            Socket listener = (Socket)AR.AsyncState;
            Socket handler = listener.EndAccept(AR);
            // Create the state object.
            StateObject state = new StateObject();
            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                 new AsyncCallback(ReceiveCallback), state);
    }


    private void menuItem1_Click(Object sender, System.EventArgs e)
    {
        this.Close();
        // Application.Exit();
        Environment.Exit(0);
    }

    private void notifyIcon1_DoubleClick(object sender, EventArgs e)
    {
        Show();
        ShowInTaskbar = true;
    }
}

I am suspecting it might be a multithreading problem, but I am new to programming and can't pinpoint. Any leads on how to resolve this issue is much appreciated.

1
Since you intended to close the app, you dont need to close the form and you should provide the code showing how you use the ManualResetEvent allDone.Mert Gülsoy
I checked removing the socket part, the close works perfectly then. So it is thread part which is the cause, I guess. I tried to close/reset the AllDo thread in the menuItem1_Click, but it has no effect.Meenakshi

1 Answers

1
votes

It works fine with this below code

 private void menuItem1_Click(Object sender, System.EventArgs e)
    {
     Application.ExitThread();
    }