Я работаю с некоторым кодом (не мой, спешу добавить, я вообще не очень доверяю) для класса, который открывает сокет, делает запросы и прослушивает ответы, которые выдают исключение в как я не могу понять, когда тестируется в Xunit. Я предполагаю то же исключение происходит "вживую", но на класс ссылается синглтон, поэтому он, вероятно, просто скрыт.
Проблема проявляется как «System.CannotUnloadAppDomainException: ошибка при выгрузке appdomain» в xunit, а внутреннее исключение - «System.ObjectDisposedException», которое выдается (по существу) внутри финализатора при закрытии сокета! Нет другой ссылки на сокет, который вызывает close и dispose защищен в классе Socket, поэтому я не уверен, как еще объект может быть удален.
Кроме того, если я просто поймаю и поглоту, исключение ObjectDisposedException завершится, когда оно достигнет строки, чтобы закрыть поток слушателя.
Я просто не понимаю, как сокет может быть утилизирован до того, как его попросят закрыть.
Мои знания о сокетах - это только то, что я узнал с момента обнаружения этой проблемы, поэтому я не знаю, предоставил ли я все, что может понадобиться SO. ЛМК если нет!
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;
}
}
}
}