当前位置:  开发笔记 > 编程语言 > 正文

问题处理插座/完成两次?

如何解决《问题处理插座/完成两次?》经验,为你挑选了1个好方法。

我正在使用一些代码(不是我的,我不得不添加,我根本不相信这一点)对于一个打开套接字,发出请求和侦听响应的类,这会以一种我可以的方式抛出异常在xunit中测试时要理解.我假设同样的异常发生在"实时"但是该类由单例引用,因此它可能只是隐藏.

问题在xunit中显示为"System.CannotUnloadAppDomainException:在卸载appdomain时出错",并且在关闭套接字时,内部异常是"System.ObjectDisposedException"抛出(基本上)在终结器内!在Socket类中没有其他引用调用close和dispose受保护的套接字,所以我不清楚该对象是如何处置的.

此外,如果我只是捕获并吸收ObjectDisposedException,则当xunit命中该行以关闭侦听器线程时,xunit会终止.

我只是不知道Socket在被要求关闭之前是如何处理的.

我对套接字的了解只是我从发现这个问题以来所学到的,所以我不知道我是否提供了所需的一切.LMK如果没有!

public class Foo
{
    private Socket sock = null;
    private Thread tListenerThread = null
    private bool bInitialised;
    private Object InitLock = null;
    private Object DeInitLock = null;

    public Foo()
    {
        bInitialised = false;

        InitLock = new Object();
        DeInitLock = new Object();
    }

    public bool initialise()
    {
        if (null == InitLock)
            return false;

        lock (InitLock)
        {
            if (bInitialised)
                return false;

            sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 8);
            sock.Bind( /*localIpEndPoint*/);
            sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(mcIP));

            tListenerThread = new Thread(new ThreadStart(listener));
            tListenerThread.Start();

            bInitialised = true;
            return true;
        }
    }

    ~Foo()
    {
        if (bInitialised)
            deInitialise();
    }

    private void deInitialise()
    {
        if (null == DeInitLock)
            return;

        lock (DeInitLock)
        {
            if (bInitialised)
            {
                sock.Shutdown(SocketShutdown.Both); //throws System.ObjectDisposedException
                sock.Close();

                tListenerThread.Abort(); //terminates xunit test!
                tListenerThread = null;

                sock = null;

                bInitialised = false;
            }
        }
    }
}

Jon Skeet.. 8

如果此对象符合垃圾回收条件并且没有其他对Socket的引用,那么套接字的终结器可能会在对象的终结器之前运行.我怀疑这就是发生在这里的事情.

在终结器中做这么多工作通常是一个坏主意(IMO).我记不起上次实现终结器了 - 如果你实现了IDisposable,你应该没问题,除非你直接引用非托管资源,这几乎总是以IntPtrs的形式.有序关闭应该是常态 - 如果程序正在关闭,或者有人忘记处理实例,那么终结器通常只应该运行.

(我知道你在开始时澄清说这不是你的代码 - 我只是想我会解释为什么它会有问题.如果你已经知道了部分/全部内容,请道歉.)



1> Jon Skeet..:

如果此对象符合垃圾回收条件并且没有其他对Socket的引用,那么套接字的终结器可能会在对象的终结器之前运行.我怀疑这就是发生在这里的事情.

在终结器中做这么多工作通常是一个坏主意(IMO).我记不起上次实现终结器了 - 如果你实现了IDisposable,你应该没问题,除非你直接引用非托管资源,这几乎总是以IntPtrs的形式.有序关闭应该是常态 - 如果程序正在关闭,或者有人忘记处理实例,那么终结器通常只应该运行.

(我知道你在开始时澄清说这不是你的代码 - 我只是想我会解释为什么它会有问题.如果你已经知道了部分/全部内容,请道歉.)

推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有