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

时间:2011-12-04 20:04:41

标签: c# .net winforms visual-studio-2010

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

除非服务器程序失去焦点,否则一切正常。失去焦点的例子是:运行服务器程序的PC启动屏幕保护程序,你点击任务栏上的时钟来查看时间,你打开另一个寡妇(Windows资源管理器,计算器......)。如果服务器程序失去焦点并且客户端尝试连接,则服务器完全关闭!如果我从Visual Studio运行服务器它不会抛出任何错误或异常。如果我正在运行已发布的服务器版本,Microsoft Windows将显示“编程无响应...”对话框。

以下是我的代码的结构:

主类中的变量:

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 Class中,构造函数如下:

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。

服务器崩溃的任何想法?

2 个答案:

答案 0 :(得分:2)

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

我的建议是将您网络的 ALL 移到UI线程之外,而不是“main”类。让它完全独立。

答案 1 :(得分:1)

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

  1. 服务器启动
  2. 进入无限循环,监听客户端连接。这个无限循环位于backgroundWorker
  3. 客户端连接到服务器。
  4. 我在textBox上打印了客户已连接的消息。 //这是问题
  5. 为了能够建立点(4)我正在使用backgroundWorker.ReportProgress方法。
  6. 要查看问题,如果焦点不在程序上(例如,正在运行屏幕保护程序),则服务器会崩溃 ,但如果焦点在程序上并且日志记录是工作。当我停止记录时,事情就好了。所以知道我知道问题的根源,但我不知道它为什么会导致崩溃;据我所知,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;
    }
    

    没什么好看的,但足以让我头疼:)谢谢你的帮助。