3

ループを含まないワーカースレッドを停止する方法が必要です。アプリケーションはスレッドを開始し、スレッドはFileSystemWatcherオブジェクトとTimerオブジェクトを作成します。これらのそれぞれにコールバック関数があります。これまでに行ったことは、揮発性のboolメンバーをスレッドクラスに追加し、タイマーを使用してこの値を確認することです。この値が設定されたら、スレッドを終了する方法に悩まされています。

    protected override void OnStart(string[] args)
    {
      try
      {
        Watcher NewWatcher = new Watcher(...);
        Thread WatcherThread = new Thread(NewWatcher.Watcher.Start);
        WatcherThread.Start();
      }
      catch (Exception Ex)
      {
          ...
      }
    }

public class Watcher
{
    private volatile bool _StopThread;

    public Watcher(string filePath)
    {
        this._FilePath = filePath;
        this._LastException = null;

        _StopThread = false;
        TimerCallback timerFunc = new TimerCallback(OnThreadTimer);
        _ThreadTimer = new Timer(timerFunc, null, 5000, 1000);
    }   

    public void Start()
    {
        this.CreateFileWatch();            
    }

    public void Stop()
    {
        _StopThread = true;
    }

    private void CreateFileWatch()
    {
        try
        {
            this._FileWatcher = new FileSystemWatcher();
            this._FileWatcher.Path = Path.GetDirectoryName(FilePath);
            this._FileWatcher.Filter = Path.GetFileName(FilePath);
            this._FileWatcher.IncludeSubdirectories = false;
            this._FileWatcher.NotifyFilter = NotifyFilters.LastWrite;
            this._FileWatcher.Changed += new FileSystemEventHandler(OnFileChanged);

            ...

            this._FileWatcher.EnableRaisingEvents = true;
        }
        catch (Exception ex)
        {
            ...
        }
    }

    private void OnThreadTimer(object source)
    {
        if (_StopThread)
        {
            _ThreadTimer.Dispose();
            _FileWatcher.Dispose();
            // Exit Thread Here (?)
        }
    }

    ...
}

したがって、スレッドが停止するように指示されたときにタイマー/ FileWatcherを破棄できますが、実際にスレッドを終了/停止するにはどうすればよいですか?

4

6 に答える 6

2

Rather than a Boolean flag, I would suggest using a ManualResetEvent. The thread starts the FileSystemWatcher, then waits on an event. When Stop is called, it sets the event:

private ManualResetEvent ThreadExitEvent = new ManualResetEvent(false);

public void Start()
{
    // set up the watcher
    this.CreateFileWatch();

    // then wait for the exit event ...
    ThreadExitEvent.WaitOne();

    // Now tear down the watcher and exit.
    // ...
}

public void Stop()
{
    ThreadExitEvent.Set();
}

This prevents you from having to use a timer, and you'll still get all your notifications.

于 2011-04-11T15:19:07.193 に答える
2

メソッドが終了すると、スレッドは終了しStartます。タイマーに到達するまでに、タイマーはすでになくなっています。

于 2011-04-11T14:54:22.463 に答える
1

あなたの場合、スレッドはすぐに終了するため、何もしません。メイン スレッドで Watcher オブジェクトを作成することもできます。

Watcher は作成スレッドが終了した後も存在し続けます。それを取り除くには、Dispose を使用します。

または、より具体的には、なぜスレッドを使用したいのですか? メインスレッドとは別のスレッドでイベントを処理するには? その場合は、Watcher イベント ハンドラーで新しいスレッドを作成します。

これも、過剰なスレッドの作成を避けるために慎重に行う必要があります。一般的な解決策は、スレッド プール/バックグラウンド ワーカーを使用することです。

于 2011-04-11T15:07:25.837 に答える
1

これを行うには、一般的に2つの方法があります

  • Thread.Abort()スレッドを中止するために使用します。これは、事実上例外をスローし、これを使用してスレッドを終了するため、非常に危険な操作と見なされます。コードが適切に準備されていない場合、これにより、リソースのリークや永久にロックされたミューテックスが非常に簡単に発生する可能性があります。私はこのアプローチを避けるだろう
  • 所定の場所で値を確認し_StopThread、メソッドから戻るか、例外をスローしてスレッドの開始に戻り、そこからスレッドを正常に終了します。これは、TPL コード ベース (キャンセル トークン) が好むアプローチです。
于 2011-04-11T14:57:23.103 に答える
0

http://msdn.microsoft.com/en-us/library/dd997423.aspx

基になる .NET Framework API は現在、ファイルまたはネットワーク I/O の進行中のキャンセルをサポートしていないため、FromAsync タスクをキャンセルすることはできません。FromAsync 呼び出しをカプセル化するメソッドにキャンセル機能を追加できますが、キャンセルに応答できるのは、FromAsync が呼び出される前または完了した後 (継続タスクなど) に限られます。

于 2011-04-11T15:08:13.327 に答える
0

Thread.Start を使用しないでください。

TPL、Rx、BackgroundWorker、またはより高いレベルのものを使用してください。

于 2011-04-11T14:55:55.463 に答える