1

時間がかかりすぎる場合Timerはキャンセルする必要があります。Thread

System.Timers.Timer timer_timers = new System.Timers.Timer();
Thread thread = new Thread(startJob);
thread.Name = "VICTIM_THREAD";

Threadメソッドを開始するときに、現在のスレッドを開始しTimer、現在のスレッドをパラメーターとしてイベントに渡します。

public void startJob()
{
    Debug.WriteLine("Name: " + Thread.CurrentThread.Name);
    timer_timers.Elapsed += (sender, e) => T_Elapsed(sender, e, Thread.CurrentThread);
    timer_timers.Interval = 5000;

    // Start simulation process
    while (true)
    {
        Thread.Sleep(700);
        Debug.WriteLine("Thread: " + Thread.CurrentThread.Name + " ALIVE: " + thread.IsAlive);
    }            
}

タイマーイベント:

private void T_Elapsed(object sender, ElapsedEventArgs e, Thread currentThread)
{
    // EDIT: show the correct NAME! of the thread
    Debug.WriteLine("Name: " + currentThread.Name);

    System.Timers.Timer tim = sender as System.Timers.Timer;

    currentThread.Abort();  // <-- this line throws exception

    if (tim != null)
    {
        tim.Stop();
    }

}

しかし、Abort呼び出しは私に例外をスローします:

「コードが最適化されているか、ネイティブ フレームがコール スタックの一番上にあるため、式を評価できません」

そしてスレッドは生き続けます。の前にタイマーを開始しstartJob()、スレッドを直接渡すと、正常に動作します。

public void startThread()
{
    timer_timers.Elapsed += (sender, e) => T_Elapsed(sender, e, thread);
    timer_timers.Interval = 5000;

    timer_timers.Start();
    thread.Start();
}
public void startJob()
{
    // Start simulation process
    while (true)
    {
        Thread.Sleep(700);
        Debug.WriteLine("Thread: " + Thread.CurrentThread.Name + " ALIVE: " + thread.IsAlive);
    }            
}

Thread.CurrentThread質問:バージョンが機能しないのはなぜですか? タイマースレッドも中止しなければならないからですか?ここで何が欠けていますか?

thisthisのようなこの例外に対して見つけた回答は、異なるコンテキストからのものであり、正確な理由を理解するのに実際には役立ちません。

編集:これがスレッドを中止またはキャンセルする間違った方法であることはわかっています。実行することになっているジョブは、SerialPort を開くことです。しかし、〜200回ごとにスレッドが返されることはなく、結果を気にせずにスレッドを強制終了する必要があります。ループ中のシミュレーションは悪い例かもしれません。

4

2 に答える 2

5

コメントに記載されているように、を使用しないでくださいAbort。使用している場合でも、使用方法の問題は次のとおりです。

タイマーはスレッドで実行されません。これらは、スレッド プール スレッドで実行されます。したがってThread.CurrentThread、ラムダで使用されるのは、そのスレッドプールスレッドになります。

タイマーを作成しているスレッドを中止したい場合は、次のことを行う必要があります。ラムダの外の変数でスレッドをキャプチャします。

Thread myThread = Thread.CurrentThread;
timer_timers.Elapsed += (sender, e) => T_Elapsed(sender, e, myThread);

ただし、スレッドをより適切に終了する方法や、明示的なスレッド化を必要としないようにコードを作り直す方法を見つける必要があります。

于 2016-07-07T13:58:20.147 に答える