web-dev-qa-db-ja.com

C#でスレッドを即座に殺す方法は?

thread.Abortメソッドを使用してスレッドを強制終了していますが、機能していません。スレッドを終了する他の方法はありますか?

private void button1_Click(object sender, EventArgs e)
{
    if (Receiver.IsAlive == true)
    {
        MessageBox.Show("Alive");
        Receiver.Abort();
    }
    else
    {
        MessageBox.Show("Dead");
        Receiver.Start();
    }
}

これを使用していますが、Aliveステータスを取得するたびに、Receiverが私のグローバルスレッドです。

47
Mobin

スレッドを強制終了するのが難しい理由は、言語設計者が次の問題を回避したいからです:スレッドはロックを取得し、それを解放する前に強制終了します。これで、そのロックが必要な人は誰でも行き詰まります。

あなたがしなければならないのは、スレッドに停止するよう指示するためにいくつかのグローバル変数を使用することです。スレッドコードで、そのグローバル変数を手動で確認し、停止する必要があることを確認したら戻る必要があります。

68
redtuna

そのようにして即座に殺すことができます:

private Thread _myThread = new Thread(SomeThreadMethod);

private void SomeThreadMethod()
{
   // do whatever you want
}

[SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
private void KillTheThread()
{
   _myThread.Abort();
}

私はいつもそれを使用し、私のために働いています:)

32
Nickon

最初に、スレッドを終了するための合意された方法が必要です。たとえば、スレッドがチェックして準拠できるrunning_変数。

メインスレッドコードは、終了時にスレッドをきれいに整頓するThreadInterruptExceptionとThreadAbortExceptionの両方をキャッチする例外ブロックでラップする必要があります。

ThreadInterruptExceptionの場合、running_変数をチェックして、続行する必要があるかどうかを確認できます。 ThreadAbortExceptionの場合は、すぐに整理してスレッドプロシージャを終了する必要があります。

スレッドを停止しようとするコードは次のことを行う必要があります。

running_ = false;
threadInstance_.Interrupt();
if(!threadInstance_.Join(2000)) { // or an agreed resonable time
   threadInstance_.Abort();
}
20
Adrian Regan

スレッドは、作業が終了すると強制終了されます。そのため、ループなどを使用している場合は、スレッドに変数を渡して、スレッドが終了した後にループを停止する必要があります。

8
Wael Dalloul

C#Thread.Abortは、スレッドを即座に中止することを保証しません。おそらく、スレッドがそれ自体でAbortを呼び出すときに機能しますが、スレッドが別のスレッドを呼び出すときは機能しません。

ドキュメントを参照してください: http://msdn.Microsoft.com/en-us/library/ty8d3wta.aspx

ハードウェアと相互作用するツールを書くこの問題に直面しました-あなたはすぐに停止したいが、それは保証されていません。私は通常、いくつかのフラグまたは他のそのようなロジックを使用して、スレッドで実行されているコードの一部の実行を防ぎます(そして、アボートで実行されたくない-トリッキーです)。

5
Sesh
    private void ResumeButton_Click(object sender, RoutedEventArgs e)
    {
        Task.Factory.StartNew(() =>
        {
            Application.Current.Resources["AutoPilotThreadStatus"] = true;
            Thread.CurrentThread.Name = "ResumeAutoPilot";
            Thread.CurrentThread.IsBackground = true;
            AutoPilotHandler.ResumeAutoPilot();
        });
    }

    public static void ResumeAutoPilot()
    {
        while ((bool)Application.Current.Resources["AutoPilotThreadStatus"])
        {
            CheckAutoPilotThreadStatus();
            var searchYoutube = YoutubeHandler.Search("small truck");
            CheckAutoPilotThreadStatus();
            SaveVideosToDatabase(searchYoutube);
            CheckAutoPilotThreadStatus();
        }
    }

    public static void CheckAutoPilotThreadStatus()
    {
        if (!(bool)Application.Current.Resources["AutoPilotThreadStatus"])
        {
            KillCurrentThread();
        }
    }

    public static void KillCurrentThread()
    {
        Thread.CurrentThread.Abort();
    }
0