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
相关产品推荐
相关产品推荐

