私は、ソケットを開き、リクエストを作成し、応答をリッスンするクラスのいくつかのコード(急いで追加するのではなく、まったく信頼していません)で作業しています。これは、可能な方法で例外をスローしていますxunitでテストしたときに理解できません。同じ例外が「ライブ」で発生すると想定していますが、クラスはシングルトンによって参照されているため、おそらく非表示になっています。
この問題は、xunit で「System.CannotUnloadAppDomainException: アプリケーション ドメインのアンロード中にエラーが発生しました」として明らかになり、内部例外は、ソケットを閉じるときにファイナライザー内で (本質的に) スローされる「System.ObjectDisposedException」です! close を呼び出して破棄するソケットへの他の参照は Socket クラスで保護されていないため、オブジェクトを他にどのように破棄できるかはわかりません。
さらに、単に ObjectDisposedException をキャッチして吸収すると、リスナー スレッドを閉じる行にヒットしたときに xunit が終了します。
ソケットを閉じるように求められる前に、ソケットを破棄する方法がわかりません。
ソケットに関する私の知識は、この問題を見つけてから学んだことだけなので、SO が必要とするすべてのものを提供したかどうかはわかりません。そうでなければ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;
}
}
}
}