使用TcpListener.AcceptSocket();在一个单独的线程导致线程阻塞? [英] Using TcpListener.AcceptSocket(); in a separate thread causes the thread to block?

查看:259
本文介绍了使用TcpListener.AcceptSocket();在一个单独的线程导致线程阻塞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试解决此问题并进行调试,但是我的处境很松散:((除了使用此方法检查客户端连接之外,还有其他选择吗?此代码在控制台应用程序中能正常工作,所以我猜猜线程是否被阻塞,尽管可能是我看不到的其他东西?

I have tried to work around this as well as debug but I'm at a loose end here :( is there any alternative to using this to check for a client connection? This code works fine in a console application so i am guessing the thread is being blocked, although it may be something else i can't see?

public partial class Form1 : Form
{
    Socket s;

套接字的声明.

private void startButton_Click(object sender, EventArgs e)
    {
        checkTimer.Enabled = true;
        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }
    }

要在按下按钮时启动的背景线程.

Background thread to start on button press.

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
        BackgroundWorker worker = sender as BackgroundWorker;

        working();
}

线程运行工作"方法.

 private void working()
 {
     if (threadFirstRun == true)
     {
            threadFirstRun = false;
     }

        try
        {

            String tempAddr = tbAddr.Text;
            IPAddress ipAd = IPAddress.Parse("147.197.204.172");
            // use local m/c IP address, and 
            // use the same in the client
            String tempPort = tbPort.Text;
            /* Initializes the Listener */
            TcpListener myList = new TcpListener(ipAd, 3000);

            /* Start Listeneting at the specified port */
            myList.Start();
            tcConnection1 = "Console:\n" + "The server is running at port 3000...";
            tcConnection2 = "\n" + "The local End point is  :" + myList.LocalEndpoint;
            tcConnection3 = "\n" + "Waiting for a connection.....";

            while (true)
            {
                s = myList.AcceptSocket();
                if (s != null)
                {
                    if (connectionEstab == false)
                    {
                        tcEstab = "\n" + "Connection accepted from " + s.RemoteEndPoint;
                        connectionEstab = true;
                    }


                    byte[] b = new byte[100];
                    int k = s.Receive(b);
                    //Console.WriteLine("Recieved...");
                    for (int i = 0; i < k; i++)
                    {
                        //Console.Write(Convert.ToChar(b[i]));
                        tcValue = tcValue + Convert.ToString(b[i]);
                        valueArray[ii] = (float)Convert.ToDouble(b[i]);
                    }
                    tcValue = tcValue + "\n";
                    ii++;
                }
                else
                {
                    Thread.Sleep(200);
                }
            }

            ASCIIEncoding asen = new ASCIIEncoding();
            s.Send(asen.GetBytes("The string was recieved by the server."));
            rtbConsole.Text = rtbConsole.Text + "\n" + "Sent Acknowledgement";
            /* clean up */
            s.Close();
            myList.Stop();
        }
        catch (Exception ex)
        {
            tcError = "\n\n" + "Error..... " + ex.StackTrace;
        }
}

工作方法启动服务器并在调用myList.AcceptSocket()时阻止;

Working method starts the server and blocks upon calling myList.AcceptSocket();?

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
        if ((e.Cancelled == true))
        {
            rtbConsole.Text = rtbConsole.Text + "\n" + "Canceled!";
        }

        else if (!(e.Error == null))
        {
            rtbConsole.Text = rtbConsole.Text + "\n\n" + ("Error: " + e.Error.Message);
        }

        else
        {
            rtbConsole.Text = rtbConsole.Text + "\n" + "Done!";
        }
}

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
        rtbConsole.Text = rtbConsole.Text + "\n" + (e.ProgressPercentage.ToString() + "%");
}

private void stopButton_Click(object sender, EventArgs e)
{
        checkTimer.Enabled = false;
        if (bw.WorkerSupportsCancellation == true)
        {
            bw.CancelAsync();
        }
}

其他一些完整性的方法.

Other methods for some completeness.

我在解释自己的问题时进行(

运行1个线程的控制台应用程序从我的android设备发送数据,但是从同一设备上的同一程序向同一ip和端口发送数据后,此Windows窗体应用程序似乎什么也没有发生.单独的线程只是处于阻塞状态,Android应用程序无法完成通信以发送数据.

Sending data from my android device is received by a console app running 1 thread, however nothing seems to happen in this windows form application upon sending data to the same ip and port from the same program on the same device. The separate thread just stays blocked and the android app cannot complete communication to send the data.

推荐答案

应该阻止.来自 MSDN :

AcceptSocket是一个阻塞方法,它返回一个您可以 用于发送和接收数据.如果要避免阻塞,请使用 确定连接请求是否可用的待定方法 传入连接队列.

AcceptSocket is a blocking method that returns a Socket that you can use to send and receive data. If you want to avoid blocking, use the Pending method to determine if connection requests are available in the incoming connection queue.

您可以将整个实现使用异步版本:

You can turn your whole implementation to use the async version: AcceptSocketAsync. Note this wont block your method, it will yield control back to the caller until a new Socket has been connected.

private async void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    await WorkingAsync();
}

WorkingAsync内部:

private Task WorkingAsync
{
    // Do all other stuff,

    Socket socket = await myList.AcceptSocketAsync();

   // Do rest of stuff with the socket
}

我建议您喜欢>什么是异步/await等价于ThreadPool服务器?以获得异步tcp连接处理程序的完整实现

I recommend you like at What is the async/await equivalent of a ThreadPool server? for a full implementation of an async tcp connection handler

这篇关于使用TcpListener.AcceptSocket();在一个单独的线程导致线程阻塞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆