You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForms中从独立类启动SCS服务器连接异常排查

问题分析与解决思路

核心问题1:SCS服务器实例被垃圾回收

你的ServerInit方法里,var server是局部变量,方法执行完毕后没有类级别的引用持有这个实例,导致.NET垃圾回收器会回收掉服务器对象,监听端口随之失效,客户端自然无法连接。

修复方案

在Server类中添加类级别的成员变量来持有服务器实例:

class Server
{
    // 类成员变量,持有服务器实例防止被GC回收
    private IScsServer _server;

    public void ServerInit()
    {
        _server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10085));
        _server.ClientConnected += Server_ClientConnected;
        _server.ClientDisconnected += Server_ClientDisconnected;
        _server.Start(); 

        Form1.Self.rtb1Text("Server has been started successfully.\n");
    }

    // 新增停止服务器的方法,对应UI的Stop按钮
    public void StopServer()
    {
        if (_server != null && _server.IsRunning)
        {
            _server.Stop();
            _server = null;
        }
    }
}

核心问题2:跨线程访问UI控件引发异常

SCS框架的客户端连接、消息接收等事件是在后台线程触发的,而WinForms控件只能在创建它们的UI线程中访问,直接调用Form1.Self.rtb1Text会触发System.InvalidOperationException。

修复方案

修改Form1中的文本更新方法,使用Invoke确保在UI线程执行操作:

public void rtb1Text(string text)
{
    // 检查是否需要跨线程调用
    if (richTextBox1.InvokeRequired)
    {
        richTextBox1.Invoke(new Action<string>(rtb1Text), text);
        return;
    }
    richTextBox1.AppendText(text);
}

public void rtb2Text(string text)
{
    if (richTextBox2.InvokeRequired)
    {
        richTextBox2.Invoke(new Action<string>(rtb2Text), text);
        return;
    }
    richTextBox2.Text = text;
}

补充优化:完善Stop按钮逻辑

在Form1的按钮点击事件中,调用新增的StopServer方法:

private void button1_Click(object sender, EventArgs e)
{
    if (button1.Text.EndsWith("Start"))
    {
        button1.Text = "Stop";
        server.ServerInit();
    }
    else if (button1.Text.EndsWith("Stop"))
    {
        button1.Text = "Start";
        server.StopServer();
    }
}

额外优化:移除静态事件处理方法

把Server类中事件处理方法的static修饰符去掉,避免依赖静态的Form1.Self引用,代码更健壮:

void Server_ClientConnected(object sender, ServerClientEventArgs e)
{
    Form1.Self.rtb1Text("A new client with ID: " + e.Client.ClientId + " has connected.\n");
    e.Client.MessageReceived += Client_MessageReceived;
}

void Server_ClientDisconnected(object sender, ServerClientEventArgs e)
{
    Form1.Self.rtb1Text("A client is disconnected! Client Id = " + e.Client.ClientId + "\n");
}

async void Client_MessageReceived(object sender, MessageEventArgs e)
{
    // 原逻辑保持不变
}

内容的提问来源于stack exchange,提问作者lemonslayer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:10:17