3

独自のスレッドで動作する多くのサードパーティ DLL を使用する WPF アプリケーションがあります。

これらの DLL の一部にはメソッドがありSTOP()ます。

私はThread.Sleep(1000)SomeObject.Stop()方法の後に使用しています...

とにかく、アプリケーションを終了すると、一部のスレッドがまだメモリ内に残っています。

この問題を解決する方法はありますか?

4

2 に答える 2

4

つまり、基本的には、サードパーティのライブラリで問題が発生し、必要なときに適切にクリーンアップできません。さらに、その上に、アプリケーションを終了したい場合でも、アプリケーションを実行し続けるための一連のフォアグラウンドスレッドがスピンアップします。

例として、このようなアプリケーション

private static void Main(string[] args)
{

    var t = new Thread(() =>
        {
            while (true)
            {
            }
        }) {Name = "test"};

    t.Start();

    Console.WriteLine("Exited");
}

t前景のスレッドな ので、永遠に座ります。

ProcessExplorerで再確認してみましょう。これがデモアプリの更新バージョンで、ピンボークしてネイティブスレッドIDを取得できます。

internal class Program
{
    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);


    [DllImport("kernel32.dll")]
    static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);

    [DllImport("kernel32.dll")]
    static extern int GetCurrentThreadId();

    private static void Main(string[] args)
    {

        var t = new Thread(() =>
            {
                Console.WriteLine(GetCurrentThreadId());
                while (true)
                {
                }
            }) {Name = "test"};

        t.Start();

        Console.WriteLine("Thread Id " + t.ManagedThreadId);
        Console.WriteLine("Exited");

    }
}

ネイティブスレッドIDを教えてください。プロセスエクスプローラーで私は今見ることができます:

紡績糸

mainがすでに終了しているにもかかわらず、whileループが原因でスレッド8228が激しく回転していることは明らかです。

一般的に、ユーザーRobHardyは正しいです。スレッドを制御する場合は、常に物事を追跡して自分で管理する必要がありますが、スレッドハンドルにアクセスできないため、ここでは問題が発生していると思います。

オプション1(ただし、しないでください)

あなたはすべてを殺そうとすることができます(しかし、とにかくそれを試したとき、それは私にとって実際にはうまくいきませんでした)、しかしそれをすることは信じられないほど危険であるように思われるので私は本当にこれをしません。他の投稿から情報をコピーするだけで、例は次のように述べています。

internal class Program
{
    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);


    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);

    private static void Main(string[] args)
    {

        var t = new Thread(() =>
            {
                while (true)
                {
                }
            }) {Name = "test"};

        t.Start();

        Console.WriteLine("Exited");

        Thread.Sleep(TimeSpan.FromSeconds(2));

        foreach (ProcessThread pt in Process.GetCurrentProcess().Threads)
        {
            IntPtr ptrThread = OpenThread(1, false, (uint)pt.Id);
            if (AppDomain.GetCurrentThreadId() != pt.Id)
            {
                try
                {
                    TerminateThread(ptrThread, 1);
                    Console.Out.Write(". Thread killed.\n");
                }
                catch (Exception e)
                {
                    Console.Out.WriteLine(e.ToString());
                }
            }
            else
                Console.Out.Write(". Not killing... It's the current thread!\n");
        }
    }
}

しかし、繰り返しになりますが、それは私にとってプロセスを止めませんでした。たぶん、.netは、強制的なネイティブ出口だけでなく、スレッドの適切な出口を待っていますか?知らない。私はProcessThreadあなたが本当に望んでいたなら、あなたが技術的に(リンクによると)からスレッドを殺すことができることを示しています(しかししないでください)

オプション2

より合理的なオプションは、Exitすべてのクリーンアップの後にコードを使用して明示的な呼び出しを追加することです(終了コード0は、クリーンな終了を示すのが通例です)

private static void Main(string[] args)
{

    var t = new Thread(() =>
        {
            while (true)
            {
            }
        }) {Name = "test"};

    t.Start();

    Console.WriteLine("Exited");

    Environment.Exit(0);
}

これは私のために働いた。

オプション3

3番目のオプションは、可能であれば、ライブラリを修正して、バックグラウンドスレッドを作成するか、適切にクリーンアップすることです。サードパーティのアイテムをクリーンアップしないことで、潜在的な破損可能な副作用を開いたままにしないため、これが最良のオプションです。ただし、ライブラリはクローズドソースであるため、これを行っていないことを前提としています。

于 2013-02-13T20:14:45.200 に答える
0

スレッドをコレクションに追加するか、ThreadPool

各スレッドで、必ずThreadAbortException

の最後の終了点で、Main()スレッドのコレクションを調べて、Abort()それぞれを呼び出します。

于 2013-02-13T12:48:49.823 に答える