4

私はThread.Join(int millisecondsTimeout)いくつかのを終了するために使用していますAppDomain

AppDomain が 5 秒以内に終了しなかったというエラー メッセージが頻繁に表示されます。デバッガーをステップ実行すると、AppDomain.Unload()呼び出しが 5 秒以内に簡単に終了することがわかりますが、 Thread.Joinfalse が返されます。

どこが間違っていますか?

var thread = new Thread(
    () =>
    {
        try
        {
            AppDomain.Unload(someAppDomain);
        }
        catch (ArgumentNullException)
        {

        }
        catch (CannotUnloadAppDomainException exception)
        {
            // Some error message
        }
    });

thread.Start();
const int numSecondsWait = 5;

if (!thread.Join(1000 * numSecondsWait))
{
    // Some error message about it not exiting in 5 seconds
}

編集 1

それぞれの機能を追加する価値がAppDomainあります。それぞれAppDomainに少なくとも 1 つの がありTimerます。コードは大まかに次のようになります (読みやすくするために、ここでは多数のクラスを 1 つにまとめていることに注意してください)。

static void Main(string[] args)
{
    _exceptionThrown = new EventWaitHandle(false, EventResetMode.AutoReset);
    _timer = new Timer(TickAction, null, 0, interval);
    try
    {
        _exceptionThrown.WaitOne();
    }
    finally
    {
        _timer.Dispose(_timerWaitHandle);
        WaitHandle.WaitAll(_timerWaitHandle);
    }
}

実際には、「メイン」スレッドが をスローThreadAbortExceptionし、finally ステートメントにジャンプし、Timer終了する前にキューが完全に排出されることを確認しています。

Timertick メソッド内にある場合、すべての がログに記録されます。したがって、タイマー キューに何もないことはほぼ確実であり、_timer.Dispose(_timerWaitHandle)すぐに戻ります。

できるかどうかに関係なく、私が行っている 3 つの s のうち少なくとも1 つが5 秒以内に完了しません。AppDomainUnload

4

2 に答える 2

3

この理由は、Unload() に関する MSDN ライブラリの記事に詳しく記載されています。

.NET Framework バージョン 2.0 には、アプリケーション ドメインのアンロード専用のスレッドがあります。これにより、特に .NET Framework がホストされている場合の信頼性が向上します。スレッドが Unload を呼び出すと、ターゲット ドメインがアンロード用にマークされます。専用スレッドがドメインのアンロードを試み、ドメイン内のすべてのスレッドが中止されます。アンマネージ コードを実行している、または finally ブロックを実行しているなどの理由でスレッドが中止されない場合、一定期間が経過すると、最初に Unload を呼び出したスレッドで CannotUnloadAppDomainException がスローされます。中止できなかったスレッドが最終的に終了した場合、ターゲット ドメインはアンロードされません。したがって、.NET Framework バージョン 2.0 では、実行中のスレッドを終了できない可能性があるため、ドメインのアンロードが保証されません。

ドメイン内のスレッドは、スレッドで ThreadAbortException をスローする Abort メソッドを使用して終了されます。スレッドはすぐに終了する必要がありますが、finally 句で予測できない時間実行し続ける可能性があります。

したがって、プログラムがその appdomain 内で実行されているスレッドを持っている理由と、中止を拒否する理由を見つける必要があります。たとえば、管理されていないコード内に埋め込まれている場合に一般的です。それらを表示するには、Debug + Windows + Threads を使用します。

于 2012-11-12T16:17:38.547 に答える
3

アプリドメインが常に 5 秒以内にアンロードされることを確認したい場合は、測定を試みることができます。たとえば、次のようなものを使用します。

var stopwatch = System.Diagnostics.Stopwatch.StartNew();
AppDomain.Unload(someAppDomain);
long elapsedMillis = stopwatch.ElapsedMilliseconds;
System.Diagnostics.Trace.Writeline("Unload duration: " + elapsedMillis + " ms");

Visual Studio (または sysinternals の DebugView ツール) の [出力] ウィンドウに表示されるはずです。

于 2012-11-12T16:18:50.913 に答える