退出没有循环的线程

发布于 2024-11-01 01:36:39 字数 1923 浏览 1 评论 0原文

我需要一种方法来停止不包含循环的工作线程。应用程序启动线程,然后线程创建一个FileSystemWatcher对象和一个Timer对象。其中每个都有回调函数。 到目前为止,我所做的就是向线程类添加一个易失性布尔成员,并使用计时器来检查该值。我对设置此值后如何退出线程感到困惑。

    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 (?)
        }
    }

    ...
}

因此,当线程被告知停止时,我可以处理 Timer / FileWatcher - 但如何实际退出/停止线程?

I need a way to stop a worker thread that does not contain a loop. The application starts the thread, the thread then creates a FileSystemWatcher object and a Timer object. Each of these has callback functions.
What I have done so far is add a volatile bool member to the thread class, and use the timer to check this value. I'm hung up on how to exit the thread once this value is set.

    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 (?)
        }
    }

    ...
}

So I can dispose the the Timer / FileWatcher when the thread is told to stop - but how do I actual exit/stop the thread?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

幻梦 2024-11-08 01:36:39

我建议使用 ManualResetEvent,而不是布尔标志。该线程启动FileSystemWatcher,然后等待事件。当调用 Stop 时,它会设置事件:

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();
}

这样您就不必使用计时器,并且您仍然会收到所有通知。

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.

香草可樂 2024-11-08 01:36:39

Start方法退出时,线程将退出。当你到达计时器时,它已经消失了。

The thread will exit when the Start method exits. By the time you get to the Timer, it's already gone.

吃兔兔 2024-11-08 01:36:39

一般来说有两种方法可以

  • 使用 Thread.Abort() 中止线程。这在很大程度上被认为是非常危险的操作,因为它将有效地抛出异常并使用它来退出线程。如果代码准备不充分,这很容易导致资源泄漏或永远锁定互斥体。我会避免这种方法
  • 在规定的位置检查 _StopThread 值,然后返回该方法或抛出异常以返回线程启动并从那里优雅地退出线程。这是 TPL 代码库(取消令牌)青睐的方法

There are generally speaking 2 ways to do this

  • Use Thread.Abort() to abort the thread. This is largely considered a very dangerous operation as it will effectively throw an exception and use this to exit the thread. This can very easily lead to leaked resources or forever locked mutexes if the code is not adequetely prepared. I would avoid this approach
  • Check the _StopThread value at prescribed places and either return out of the method or throw an exception to get back to the thread start and gracefully exit the thread from there. This is the approach favored by the TPL code base (cancellation tokens)
意中人 2024-11-08 01:36:39

在您的情况下,线程不会执行任何操作,因为它会立即退出。您也可以在主线程中创建 Watcher 对象。

即使创建线程终止后,观察者仍继续存在。要摆脱它,请使用 Dispose。

或者,更具体地说,为什么要使用线程?在与主线程不同的线程上处理事件?在这种情况下,请在 Watcher 事件处理程序中创建一个新线程。

必须再次小心地完成此操作,以避免创建过多的线程。典型的解决方案是使用线程池/后台工作者。

In your case, the thread does not do anything as it exits right away. You could create the Watcher object in your main thread as well.

The Watcher continues to exist even after the creating thread terminated. To get rid of it, use Dispose.

Or, more specifically, why do you even want to use a thread? To handle the events on a different thread from the main thread? In that case, create a new thread in the Watcher event handler.

This again has to be done carefully to avoid excessive thread creation. A typical solution is to use a thread pool / background workers.

垂暮老矣 2024-11-08 01:36:39

不要使用 Thread.Start !

使用 TPL、Rx、BackgroundWorker 或更高级别的东西。

Do not use Thread.Start !

Use TPL, Rx, BackgroundWorker or something higher level.

逆蝶 2024-11-08 01:36:39

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

您无法取消 FromAsync 任务,因为底层 .NET Framework API 当前不支持正在进行的文件或网络 I/O 取消。您可以向封装 FromAsync 调用的方法添加取消功能,但只能在调用 FromAsync 之前或完成之后(例如,在延续任务中)响应取消。

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

You cannot cancel a FromAsync task, because the underlying .NET Framework APIs currently do not support in-progress cancellation of file or network I/O. You can add cancellation functionality to a method that encapsulates a FromAsync call, but you can only respond to the cancellation before FromAsync is called or after it completed (for example, in a continuation task).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文