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

Visual Studio多窗体关闭后重新打开UDP读取器出现错误的技术问询

解决UDP读取器二次打开窗体报错的问题

看起来你遇到的问题本质是UdpClient资源没有正确释放,导致端口被占用。让我一步步帮你分析和解决:

问题根源

每次点击按钮创建Form1实例时,都会初始化一个新的UdpClient并绑定到5000端口。但当你关闭Form1时,这个UdpClient并没有被主动关闭和释放——操作系统会认为该端口仍被占用(或者处于TIME_WAIT状态),第二次尝试绑定同个端口就会抛出"端口已被使用"的异常。

另外还有个隐藏问题:你的recv回调是在后台线程执行的,直接访问UI控件(比如richTextBox1)会触发跨线程操作异常,这个也需要一起修复。

修复方案

我们需要在窗体关闭时主动释放UdpClient资源,同时处理跨线程UI访问的问题:

修改Form1代码

namespace UDP_TEST_2 {
    public partial class Form1 : Form {
        double x;
        UdpClient Client; // 先声明,延迟到Load中初始化
        string data; // 补充你之前缺失的data变量声明

        void recv(IAsyncResult res) {
            try {
                IPEndPoint RemoteIP = new IPEndPoint(IPAddress.Any, 5000);
                byte[] received = Client.EndReceive(res, ref RemoteIP);
                data = Encoding.UTF8.GetString(received);
                
                // 跨线程更新UI必须用Invoke
                UpdateRichTextBox(data);

                // 继续监听下一个数据包
                Client.BeginReceive(new AsyncCallback(recv), null);
            } catch (ObjectDisposedException) {
                // 当UdpClient已被释放时,停止接收,避免报错
                return;
            } catch (Exception ex) {
                UpdateRichTextBox($"错误: {ex.Message}");
            }
        }

        // 封装跨线程更新RichTextBox的方法
        private void UpdateRichTextBox(string text) {
            if (richTextBox1.InvokeRequired) {
                richTextBox1.Invoke(new Action(() => {
                    richTextBox1.Text += text + Environment.NewLine;
                }));
            } else {
                richTextBox1.Text += text + Environment.NewLine;
            }
        }

        private void Form1_Load(object sender, EventArgs e) {
            timer1.Tick += timer1_Tick;
            timer1.Interval = 1;
            try {
                Client = new UdpClient(5000); // 在这里初始化UdpClient
                Client.BeginReceive(new AsyncCallback(recv), null);
            } catch (Exception ex) {
                UpdateRichTextBox($"初始化错误: {ex.Message}");
            }
        }

        private void timer1_Tick(object sender, EventArgs e) {
            // 你的数据处理逻辑
        }

        // 添加窗体关闭事件,释放UdpClient资源
        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            // 先关闭UdpClient,停止接收
            Client?.Close();
            // 释放资源
            Client?.Dispose();
        }
    }
}

关键修改点说明

  • 资源释放:通过FormClosing事件,在窗体关闭时主动关闭并释放UdpClient,确保端口被及时释放,下次打开窗体时可以重新绑定。
  • 跨线程UI访问:新增UpdateRichTextBox方法,用Invoke确保UI操作在主线程执行,避免跨线程异常。
  • 异常处理:捕获ObjectDisposedException,当UdpClient已被释放时停止接收逻辑,防止崩溃。

这样修改后,你第二次点击按钮打开Form1时,就不会再出现端口占用的错误了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 19:27:52