C# bind & listen -> unbind & listenstop

        private void Stopbutton_Click(object sender, EventArgs e)
        {
            loop = false;
            try
            {
                foreach (Socket x in ClientSocketList)
                {
                    x.Shutdown(SocketShutdown.Both);
                    x.Close();
                }

                ServerSocket.Close();
                ServerSocket.Dispose();
            }
            catch (Exception ex)
            {
            }
            WriteToRichBox("Server Closed");
        }
        private void SAE_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket socket = sender as Socket;
            if (socket.Connected && socket.Poll(1, SelectMode.SelectRead) == false)
            {
                WriteToRichBox(e.Buffer);
                socket.ReceiveAsync(e);
                socket.Send(StringToByte(" Response from server!\r\n"));
            }
            else
            {
                e.Completed -= SAE_Completed;
                WriteToRichBox("Client Disconnected " + socket.LocalEndPoint);
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }
        Socket ServerSocket;
        List<Socket> ClientSocketList = new List<Socket>();
        bool loop = false;
        private async void Listener(int Port)
        {
            ServerSocket = new Socket(SocketType.Stream, ProtocolType.IP);
            ServerSocket.Bind(new IPEndPoint(IPAddress.Loopback, Port));
            ServerSocket.Listen(0);
            WriteToRichBox("Server Started");
            while (loop)
            {
                try
                {
                    Socket ClientSocket = await ServerSocket.AcceptAsync();

                    if (ClientSocket.Connected)
                    {
                        WriteToRichBox("Connected Client from" + ClientSocket.LocalEndPoint);
                        ClientSocketList.Add(ClientSocket);
                        byte[] ClientBuffer = new byte[1024];
                        var SAE = new SocketAsyncEventArgs
                        {
                            UserToken = ClientSocket,
                            RemoteEndPoint = ClientSocket.RemoteEndPoint,

                        };
                        SAE.SetBuffer(ClientBuffer, 0, ClientBuffer.Length);

                        SAE.Completed += SAE_Completed;//이벤트가 완료되면 실행될 함수 등록
                        ClientSocket.ReceiveAsync(SAE);//데이터를 다받으면 실행될 이벤트
                    }
                }
                catch
                {
                    return;
                }
            }
        }

서버 코드는 이런식으로 짜져있습니다.
서버소켓과 클라이언트 소켓의 리스트가 전역으로 잡혀있습니다.
클라이언트가 접속되지 않은 상태에서 서버의 소켓을 close 할경우 포트도 잘닫히고 이후 접속이 안되긴 합니다.
저는 버튼 두개를 만들어서 하는 listen 버튼 다른 하나는 stop 버튼으로 버튼으로 서버를 제어하도록 짜려고 합니다.
근데 문제는 클라이언트가 서버에 접속된 상태에서 서버를 닫아버리면
스레드 종료 또는 응용 프로그램 요청 때문에 I/O 작업이 취소되었습니다
라는 오류를 뿜으면서 서버 프로그램이 강제로 종료됩니다.
서버 프로그램의 목적은 1:N 채팅 프로그램이고 특정 사용자를 추방하거나, 서버를 끄고 닫아도 문제없도록 만들려고 하는데 클라이언트가 접속된 상태에서 서버를 끄려고 서버쪽 클라이언트의 소켓을 닫아준뒤에 최종적으로 서버의 소켓을 닫게되는데
스레드 종료 또는 응용 프로그램 요청 때문에 I/O 작업이 취소되었습니다
라는 에러가 계속 떠서 async await 으로 소켓서버를 열고 닫는 방법이 없는지 궁금합니다.

유저를 강퇴하거나 유저의 정보를 서버에서 보려면 클래스로 구현하는게 좋을까요 아니면 listview나 listbox를 활용하는게 좋을까요 ?