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

UDP Client调用BeginReceive后如何关闭?Dynamics Nav实例化遇阻

解决UDP Client在BeginReceive后的正确关闭方法

我之前也碰到过类似的UDP异步接收后无法正常关闭的坑,结合.NET UDP客户端的最佳实践,给你整理一套能在Dynamics NAV里稳定运行的关闭流程:

核心问题根源

UDP本身是无连接协议,但用BeginReceive开启异步接收后,客户端会处于持续等待状态。如果直接调用Close(),后台的异步操作可能还在占用套接字资源,导致端口没有真正释放,自然无法重新实例化类。

正确关闭的步骤

  • 先终止异步等待:用UdpClient.Client.Shutdown(SocketShutdown.Both)强制终止套接字的收发操作,让等待中的BeginReceive立即返回,避免后续逻辑卡住。
  • 用标志位控制回调逻辑:定义一个全局的布尔标志(比如_isClosing),在回调方法里先判断这个标志,避免关闭后还继续处理数据或发起新的接收请求。
  • 最后清理资源:调用Close()后,务必手动调用Dispose()释放资源,或者让类实现IDisposable接口,确保资源被彻底回收。

完整代码示例(适配COM接口+Dynamics NAV)

using System;
using System.Net;
using System.Net.Sockets;

[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.Guid("这里替换成你的GUID")]
public class UdpNavReceiver : IDisposable
{
    private UdpClient _udpClient;
    private bool _isClosing = false;
    private IPEndPoint _remoteEndPoint;

    public void StartListening(int listenPort)
    {
        _remoteEndPoint = new IPEndPoint(IPAddress.Any, listenPort);
        _udpClient = new UdpClient(listenPort);
        // 启动异步接收
        BeginReceive();
    }

    private void BeginReceive()
    {
        // 如果正在关闭,不再发起新的接收
        if (_isClosing) return;
        _udpClient.BeginReceive(ReceiveCallback, null);
    }

    private void ReceiveCallback(IAsyncResult ar)
    {
        // 先判断是否正在关闭,避免无效操作
        if (_isClosing)
        {
            _udpClient.EndReceive(ar, ref _remoteEndPoint);
            return;
        }

        try
        {
            byte[] receivedData = _udpClient.EndReceive(ar, ref _remoteEndPoint);
            // 这里处理接收到的UDP数据包,比如转成字符串或传递给NAV的逻辑

            // 继续监听下一个数据包
            BeginReceive();
        }
        catch (ObjectDisposedException)
        {
            // 客户端已关闭,忽略该异常
        }
        catch (Exception ex)
        {
            // 按需处理其他异常,比如写入日志
        }
    }

    public void StopAndClose()
    {
        _isClosing = true;
        try
        {
            // 先终止套接字的所有操作
            _udpClient.Client.Shutdown(SocketShutdown.Both);
        }
        catch (Exception)
        {
            // 如果套接字已经关闭,直接忽略这个异常
        }
        finally
        {
            // 关闭并释放客户端资源
            _udpClient.Close();
            _udpClient.Dispose();
        }
    }

    public void Dispose()
    {
        StopAndClose();
    }
}

针对Dynamics NAV的额外注意事项

  • 确保你的COM类实现了IDisposable接口,这样NAV可以正确触发资源释放逻辑。
  • 在NAV代码里,调用完StopAndClose()后,务必销毁类实例,避免残留的资源占用端口。
  • 测试时如果遇到端口仍被占用的情况,可能需要重启NAV服务彻底释放资源,但只要严格按上述流程执行,大概率不会出现这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:56:55