为什么在启动服务器tcp时,表单消失了?

时间:2016-09-05 10:29:15

标签: c# forms

我有一个带有button1和此代码的表单

private void button1_Click(object sender, EventArgs e)
{
    ServerTCP s = new ServerTCP();   
}

然后是class serverTCP

public ServerTCP()
{
    TcpListener listen = new TcpListener(IPAddress.Any, 1200);
    Console.WriteLine("Waiting");
    listen.Start();
    while (true)
    {
        TcpClient client = listen.AcceptTcpClient();
        Console.WriteLine("Client connected");
        NetworkStream stream = client.GetStream();
        byte[] buffer = new byte[client.ReceiveBufferSize];
        int data = stream.Read(buffer, 0, client.ReceiveBufferSize);
        string message = Encoding.Unicode.GetString(buffer, 0, data);
        int idgiorno = Int32.Parse(message);
        Console.WriteLine("idgiorno: " + idgiorno);
        client.Close();
     }
 }

问题是在我点击button1后,表单消失了。我可以从开始栏看到它仍然在运行,但即使我点击它的图标,也没有显示它。这就像形式失去了焦点。

2 个答案:

答案 0 :(得分:0)

好吧,基本上以下调用永远不会返回:

ServerTCP s = new ServerTCP();   

ServerTcp的构造函数包含无限循环,因此调用永远不会返回,它也会阻止UI线程。使用阻塞的UI线程时,永远不会处理WM_ACTIVATE或WM_PAINT等窗口消息,因此您的表单将无法使用。

你真的应该考虑异步使用TcpListenerThis is a good starting point。然后,您将删除循环,因为重复调用BeginAcceptTcpClient将使服务器保持运行。

答案 1 :(得分:0)

我可以看到你在这里尝试做什么,但即使你解决了这个问题,我也担心你会遇到麻烦。

首先,正如之前所说的那样,你失去形式的原因是因为你在主线程上进入了一个无限循环。为避免这种情况,请尝试使用;

using System.Threading.Tasks
public ServerTCP()
{
    TcpListener listen = new TcpListener(IPAddress.Any, 1200);
    Console.WriteLine("Waiting");
    listen.Start();
    Task myTask = new Task(() =>
    {
        while (true)
        {
            TcpClient client = listen.AcceptTcpClient();
            Console.WriteLine("Client connected");
            NetworkStream stream = client.GetStream();
            byte[] buffer = new byte[client.ReceiveBufferSize];
            int data = stream.Read(buffer, 0, client.ReceiveBufferSize);
            string message = Encoding.Unicode.GetString(buffer, 0, data);
            int idgiorno = Int32.Parse(message);
            Console.WriteLine("idgiorno: " + idgiorno);
            client.Close();
        }
    });
    myTask.Start();
}

这是一种将任务分配到池中的备用线程而不必自己创建管理线程的惰性方法。该委托称为lambda表达式;

https://msdn.microsoft.com/en-GB/library/bb397687.aspx

这个问题是这个线程无论如何都无法访问控制台资源,所以我担心你不会看到你的消息。

在您的代码中,您已经编写了所有内容"程序上"。这意味着您已经编写了一份说明列表,假设每个步骤都准备好了必备条件。例如;

 byte[] buffer = new byte[client.ReceiveBufferSize];

如果您还没有收到数据,那么您将尝试初始化0为零的缓冲区,世界将会结束。

请不要试图逐步引导您完成这一切,请将这两个YouTube视频视为精彩的介绍。他们并不完美,但应该有助于你进一步前进;

https://www.youtube.com/watch?v=uXFso7xSSWk

https://www.youtube.com/watch?v=NanjpGKC2js

真的,接近你的应用程序的唯一有效方法是通过"事件驱动编程",但这可能是另一天的事情。

祝你好运!