0

ThreadPool.QueueUserWorkItem コマンドを介して実行時間の長いタスクを開始するプロセスがあります。

内部の各タスクは、AppDomain.CreateDomain 呼び出しを介して新しい AppDomain を読み込み、一連のものを処理して終了します。場合によっては、これらのアプリ内の処理に時間がかかりすぎて、実行時間が長すぎると中止する必要があります。

AppDomains が適切にアンロードされるように、知らないうちにこれらのスレッドを外部から中止できるかどうかを知りたいですか?

以下のコードでわかるように、現在 appdomain はローカル変数として作成されていますが、必要に応じてクラス メンバーに移動できます。スレッドを強制終了するための最善の方法は、try/catch 全体の「finally」句で行われるように、その appdomain をアンロードすることです。ただし、AsyncExecute は中止する呼び出し元とは別のスレッドで実行されるため、「外部から」(appdomain) にアクセスできるかどうかはわかりません。

タスクの処理を開始する関数は次のとおりです。

public void AsyncExecute(RunningState runningState)
{
  RunningState returnedState = null;
        AppDomain runningApp = null;

        try
        {
            {

                var ads = new AppDomainSetup
                              {
                                  ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
                                  DisallowBindingRedirects = false,
                                  DisallowCodeDownload = false,
                                  ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
                              };
                runningApp = AppDomain.CreateDomain("RemoteMonitor_" + runningState.LocalAccountInfo.Id, null,
                                                    ads);
                var sub =
                    runningApp.CreateInstanceAndUnwrap("Processor", "Processor.ProcessorSub")
                    as ProcessorSub;
                if (sub != null)
                {
                    returnedState = sub.Run(runningState);
                }
                else
                    Logger.Instance.WriteCritical<ExecutableItem>("Cannot create Processor object");
            }
        }
        catch (Exception ex)
        {
            Logger.Instance.WriteError<ExecutableItem>(                        ex.Message, ex);
        }
        finally
        {
            if (runningApp != null)
                AppDomain.Unload(runningApp);

            if (_onCompleteHandler == null)
                Logger.Instance.WriteCritical<ExecutableItem>("Cannot complete task");
            else
                _onCompleteHandler.Invoke(returnedState);
        }
}
4

1 に答える 1

0

1 つの基本的なポイントと、私が卵を吸う方法を教えている場合は、前もって多くの謝罪をしてください。スレッド プールに送信されたタスクは、必ずしもすぐに実行されるとは限りません。プール内のスレッドの 1 つが解放されるまで待ってから開始します。

そのため、QueueUserWorkItem を呼び出したときに既にいくつかのスレッド プール タスクが実行されている場合、新しいタスクは待機する必要があります。QueueUserWorkItem() を呼び出したときと、try ブロックの最初の行に到達したときにもう一度ログに記録することで、これに該当するかどうかを確認できます。これら 2 つのログ エントリ間の大きな時間差は、原因を裏切っています。

スレッド プール内のスレッドの数を増やすことができます。

ブロックされているものを中止することは、多くの言語できれいに行うのが難しいです。本当にそれをしなければならない唯一の理由は、スレッドプールスレッドを使用しているためです。ただし、それが適切なスレッドである場合、タスクに時間がかかっていても問題ありません。遅延がドメイン コントローラーの応答を待機することであると仮定すると、スレッドはブロックされたソケット読み取りでスタックする可能性が最も高くなります。もしそうなら、それはプロセッサ時間を消費しておらず、自然に完了するかあきらめるのに自然にかかる時間の間、ぶらぶらしていてもそれほど害はありません.

于 2013-05-07T23:44:05.287 に答える