1

動的に作成されたスレッドのグループを終了するのに問題があります。これらすべてを任意の時点で終了する必要がある理由は、フォームの特定の部分を更新して新しい部分を作成できるようにするためです。これが私のスレッドで何が起こるかを示す簡単なシナリオです。

いくつかのスレッドは、インプレースの特定の変数に基づいて動的に作成されます。

 for (int i = 0; i <= mDevices.Count; i++)
        {
            ThreadStart workerThread = delegate { pollDevices(mDevices[i - 2], this); };
            new Thread(workerThread).Start();
        }

  public void pollDevices(IDeviceInterface device, DeviceManager mainUI)
    {
       System.Timers.Timer timer = null;
        if (timer == null)
        {

            timer = new System.Timers.Timer(1000);
            timer.Elapsed += delegate(object sender, ElapsedEventArgs e) { timerElapsed(sender, e, device, mainUI); };

        }
        timer.Enabled = true;

 public void timerElapsed(object sender, ElapsedEventArgs e, IDeviceInterface device, DeviceManager mainUI)
    {


         device.connect(device, this);
        //wait till thread finishes and destroy
         Thread.CurrentThread.Abort();
    }

次に、これらのスレッドはタイマーで動作し、UIの更新などを処理するイベントを処理します。ただし、UIを更新しようとすると(たとえば、データベース内のエントリをさらに考慮する必要がある場合)、スレッドがまだ実行されている場合、フォーム上のボタン(これらはスレッドに割り当てられています)を削除するとエラーが発生します。この方法で現在のすべてのスレッドを停止する必要がある更新を要求します。

だから私の質問は、UIを更新する前にこのスレッドのグループを中止するにはどうすればよいですか?

4

3 に答える 3

2

いくつかの問題があります。

  • ループ変数を閉じています。
  • タイマーを開始するためだけにスレッドを作成しています...メインスレッドでタイマーを開始しないのはなぜですか?
  • タイマー インスタンスはルート化されていないため、処理が完了する前にガベージ コレクションの対象になる可能性があります。
  • System.Timers.Timerイベント ハンドラーはスレッドで実行されるため(ThreadPool少なくともこの場合)、これらのスレッドの 1 つを中止しようとしてもうまくいきません。

ここには十分な問題があるため、主要な質問に答える前に、重要な再構築を行う必要があります。ただし、もう 1 つのヒントとして、メインの UI スレッド以外のスレッドから UI 要素にアクセスしたり操作したりしないでください。

于 2012-05-31T13:20:50.053 に答える
0

スレッド プロシージャ内でタイマーを使用するのはなぜですか?

ManualResetEvent exit = new ManualResetEvent(false);
for (int i = 0; i <= mDevices.Count; i++)
    {
        ThreadStart workerThread = delegate { pollDevices(mDevices[i - 2], this, exit); };
        new Thread(workerThread).Start();
    }

public void pollDevices(IDeviceInterface device, DeviceManager mainUI, ManualResetEvent exit)
{
    while(!exit.WaitOne(1000))
    {
         // do work
         device.connect(device, this);
    }
}

次に、すべてのスレッドを停止する場合は、exit.Set() を呼び出します。

于 2012-05-31T09:55:43.320 に答える
0

私はこれをソリューションの1つで使用していますhttp://msdn.microsoft.com/en-us/magazine/cc163644.aspx

それは AbortableThreadPool です。あなたのために働くかもしれません。

とにかく終了しているスレッドで timerElapsed で Thread.Abort を呼び出す理由についても少し混乱しています

于 2012-05-31T09:56:01.440 に答える