TCP client connection freezes program

僤鯓⒐⒋嵵緔 提交于 2019-12-25 18:36:20

问题


I'd like to have an asynchronous continuous ping request on a ip + port. The problem is, when the targeted server is offline, the whole program freezes during request time. But this shouldn't happen.

This is my ping function which is called once when starting the program. It should do a ping request every 3 seconds.

    public async void Start(string ip)
    {
        Stopwatch watch = new Stopwatch();

        while (true)
        {
            watch.Restart();
            using (TcpClient tcp = new TcpClient())
            {
                //try to connect to a closed port
                IAsyncResult res = tcp.ConnectAsync("127.0.0.1", 1234);

                //during the following while-loop the whole program freezes
                //although this is an asynchronous function
                while (watch.ElapsedMilliseconds < 1000) 
                {
                    if (tcp.Connected)
                    {
                        break;
                    }
                }
                watch.Stop();
                if (tcp.Connected)
                {
                    StatusControl.Text = watch.ElapsedMilliseconds.ToString() + " ms";
                }
                else
                {
                    StatusControl.Text = "Offline";
                }
            }
            //wait 3secs for the next request
            await Task.Delay(3000);
        }
    }

回答1:


If you want your application to remain responsive and not hang, you cannot build your own loop and keep the thread occupied. Instead, let C# take care of managing the Task for you by using the await keyword. Instead of looping and checking for timeout, just set a timeout on the request using SendTimeout. Here is an example:

    public async void Start(string ip)
    {
        label1.Text = "Begin";
        Stopwatch watch = new Stopwatch();

        while (true)
        {
            watch.Restart();
            using (TcpClient tcp = new TcpClient())
            {
                //try to connect to a closed port
                // First set a timeout value
                tcp.SendTimeout = 1000;
                try
                {
                    await tcp.ConnectAsync("127.0.0.1", 1234);
                }
                catch (SocketException)
                {
                    Debug.Assert(!tcp.Connected);
                }

                watch.Stop();
                if (tcp.Connected)
                {
                    label1.Text = watch.ElapsedMilliseconds.ToString() + " ms";
                }
                else
                {
                    label1.Text = "Offline";
                }
            }
            //wait 3secs for the next request
            await Task.Delay(3000);
        }
    }
}



回答2:


If you want to do an asynchronous ping request to a port along with a timeout, this code did it for me:

    private async Task<long> Ping(string host, int port, int timeOut)
    {
        long elapsed = -1;
        Stopwatch watch = new Stopwatch();

        using (TcpClient tcp = new TcpClient())
        {
            try
            {
                using (CancellationTokenSource cts = new CancellationTokenSource())
                {
                    StartConnection(host, port, tcp, watch, cts);
                    await Task.Delay(timeOut, cts.Token);
                }
            }
            catch {}
            finally
            {
                if (tcp.Connected)
                {
                    tcp.GetStream().Close();
                    elapsed = watch.ElapsedMilliseconds;
                }
                tcp.Close();
            }
        }

        return elapsed;
    }

    private async void StartConnection(string host, int port, TcpClient tcp, Stopwatch watch, CancellationTokenSource cts)
    {
        try
        {
            watch.Start();
            await tcp.ConnectAsync(host,port);
            watch.Stop();
            cts.Cancel();
        }
        catch {}
    }

It simply disposes the tcpClient as soon as the time is over and returns -1 when the server is offline or something went wrong.



来源:https://stackoverflow.com/questions/28729662/tcp-client-connection-freezes-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!