c#服务器关闭/崩溃,如果客户端在服务器失去焦点时连接到它(例如,屏幕保护程序正在运行)

本文关键字:服务器 例如 屏幕保护 运行 程序 连接 焦点 崩溃 如果 失去 客户端 | 更新日期: 2023-09-27 18:16:49

我正在使用TCP套接字编写客户机-服务器应用程序。服务器端是使用Visual Studio 2010编写的。NET 4.0)。服务器允许多个客户端连接在同一时间,因此我使用异步。风格。服务器需要连接到数据库(MySQL),而服务器程序正在运行,我需要与数据库进行交互。出于这个原因,我使用BackgroundWorker来运行无限监听循环(将接受客户端),以防止接口冻结,并能够从可视化界面访问数据库。

一切正常,除非服务器程序失去焦点。失去注意力的例子有:正在运行服务器程序的电脑启动了屏幕保护程序,你点击任务栏上的时钟查看时间,你打开另一个寡妇(windows资源管理器,计算器…)。如果服务器程序失去焦点并且客户端试图连接,服务器将完全关闭!如果我从Visual Studio运行服务器,它不会抛出任何错误或异常。如果我运行的是已发布版本的服务器,Microsoft Windows将显示"Programming not responding…"对话框。

下面是我的代码结构:

主类中的变量:

const int portNo  = 12345;
static System.Net.IPAddress localAdd = System.Net.IPAddress.Parse("192.168.1.67");
static TcpListener tcpListenerReadWrite  = new TcpListener(localAdd, portNo);

在主表单中,一个按钮启动服务器:

private void button1_Click(object sender, EventArgs e)
{
    tcpListenerReadWrite.Start();
    backgroundWorker1.RunWorkerAsync();
}

后台工作DoWork函数:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    while (true)
    {
        ChatClient clientRead = new ChatClient(tcpListenerReadWrite.AcceptTcpClient());
    }
}

在Server类中,构造函数如下:

public ChatClient(TcpClient client) //constructor
{
    _client = client;
    _clientIP = client.Client.RemoteEndPoint.ToString();
    //start reading data from the client in a separate thread
    data = new byte[_client.ReceiveBufferSize];
    _client.GetStream().BeginRead(data, 0, Convert.ToInt32(_client.ReceiveBufferSize), ReceiveMessage, client);
}

服务器收到消息时:

public void ReceiveMessage(IAsyncResult asyncResult)
{
    //read received message from client
}

最后两个注意事项:(1)当客户端连接到服务器时,它做的第一件事是向服务器发送消息,如Hello消息,(2)在可视界面中编写服务器之前,我在控制台模式下测试它,这个问题不存在,屏幕保护程序用来运行,没有发生任何事情。当然,在控制台模式下我没有使用任何BackgroundWorker。

知道为什么服务器会崩溃吗?

c#服务器关闭/崩溃,如果客户端在服务器失去焦点时连接到它(例如,屏幕保护程序正在运行)

它是否与在主UI线程上创建的TcpListener有关,而不是您的后台线程?您自己说过,这不会发生在控制台应用程序中。我怀疑,因为你现在有一些UI元素,它不是那么明确。

我的建议是移动所有你的网络在UI线程之外,而不是在'main'类。让它完全独立。

我发现是什么让我的服务器崩溃了(这花了我一些时间,因为我最近专注于客户端编程,今天我又回到了服务器编程)。正如@Moo-Juice所建议的,这是一个与访问UI相关的问题。实际上,下面是导致崩溃的场景:

  1. 服务器启动
  2. 进入一个无限循环,监听客户端连接。这个无限循环在backgroundWorker .
  3. 客户端连接到服务器。
  4. 我在textBox上打印一条客户端已连接的消息。//问题在这里
  5. 为了能够建立点(4),我使用backgroundWorker.ReportProgress方法。

回顾一下这个问题,如果焦点不在程序上(例如正在运行屏幕保护程序),服务器只会在崩溃,但是如果焦点在程序上并且日志正在工作,则不会崩溃。当我停止伐木时,一切都好起来了。所以我知道问题的根源,但我不知道为什么它会导致崩溃;据我所知,ReportProgress被设计用于向用户界面报告进度。无论如何,我现在将试着解决这个问题,特别是我知道从哪里去。如果您有兴趣了解我是如何进行日志记录的,下面是我使用的函数:

private void PrintString(string stringToPrint)
{
    var myForm = Form1.ActiveForm as Form1;
    myForm.backgroundWorker1.ReportProgress(1, stringToPrint);
}

ReportProgress函数:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    textBox1.Text += (string)e.UserState;
    textBox1.Text += Environment.NewLine;
}

没有那么花哨,但足以让我头疼:)谢谢你的帮助。