ann*_*ata 2 c# sockets dispose xunit finalizer
我正在使用一些代码(不是我的,我不得不添加,我根本不相信这一点)对于一个打开套接字,发出请求和侦听响应的类,这会以一种我可以的方式抛出异常在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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果此对象符合垃圾回收条件并且没有其他对Socket的引用,那么套接字的终结器可能会在对象的终结器之前运行.我怀疑这就是发生在这里的事情.
在终结器中做这么多工作通常是一个坏主意(IMO).我记不起上次实现终结器了 - 如果你实现了IDisposable,你应该没问题,除非你直接引用非托管资源,这几乎总是以IntPtrs的形式.有序关闭应该是常态 - 如果程序正在关闭,或者有人忘记处理实例,那么终结器通常只应该运行.
(我知道你在开始时澄清说这不是你的代码 - 我只是想我会解释为什么它会有问题.如果你已经知道了部分/全部内容,请道歉.)
| 归档时间: |
|
| 查看次数: |
4307 次 |
| 最近记录: |