简体   繁体   English

每n秒唤醒一次线程

[英]Waking thread every n seconds

I am writing a WPF application using C# and I need some help with threading. 我正在使用C#编写WPF应用程序,并且需要一些有关线程的帮助。 I have three classes, each need to be running a task every n seconds in their own thread. 我有三个类,每个类需要在自己的线程中每n秒运行一次任务。 This is how I did it with Qt4: 这是我用Qt4做到的:

class myThread : public QThread
{
    void run (void)
    {
        while (true)
        {
            mMutex.lock();
            mWaitCondition.wait (&mMutex);

            // Some task

            mMutex.unlock();
        }
    }

    void wait (int timeout)
    {
        // For shutdown purposes
        if (mMutex.tryLock (timeout))
            mMutex.unlock();
    }

    void wake (void)
    {
        mWaitCondition.wakeAll();
    }
}

// Some other class has a timer which ticks
// every n seconds calling the wake function
// of the myThread class.

What I get from this is a controlled update interval. 我从中得到的是一个受控的更新间隔。 So if I am updating 60 times a second, if the code is slow and can only run 30 times a second, it has no problem doing that, but it will never run more than 60 times a second. 因此,如果我每秒更新60次,如果代码运行缓慢并且每秒只能运行30次,那么这样做没有问题,但是它永远不会每秒运行60次以上。 It will also not run the same code more than one time at the same time. 它也不会在同一时间多次运行同一代码。 Whats the easiest way of implementing this in C#? 在C#中最简单的实现方法是什么?

You should use a Timer instead. 您应该改为使用Timer

Read this article for details, or this one for a more compact explanation. 阅读这篇文章的详细信息,或这一个更紧凑的解释。

.NET Reactive Extensions允许进行复杂的基于时间的异步事件组合- 可能是与时间相关的行为的良好起点。

You can use there classes for do this 您可以使用那里的类来做到这一点

using System;
using System.Timers;
using System.Threading;

public class ClassTask
{
    System.Timers.Timer timer = null;

    public bool IsRunning { get; set; }

    public DateTime LastRunTime { get; set; }

    public bool IsLastRunSuccessful { get; set; }

    public double Interval { get; set; }

    public bool Stopped { get; set; }

    public ClassTask(double interval)
    {
        this.Interval = interval;
        this.Stopped = false;
        timer = new System.Timers.Timer(this.Interval);
        timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        timer.Enabled = true;
    }
    public void Start()
    {
        this.Stopped = false;
        this.StartTask();
    }

    public void Stop()
    {
        this.Stopped = true;
    }

    private void StartTask()
    {
        if (!this.Stopped)
        {
            //Thread thread = new Thread(new ThreadStart(Execute));
            //thread.Start();
            Execute();
        }
    }

    private void Execute()
    {
        try
        {
            this.IsRunning = true;
            this.LastRunTime = DateTime.Now;

            // Write code here

            this.IsLastRunSuccessful = true;
        }
        catch
        {
            this.IsLastRunSuccessful = false;
        }
        finally
        {
            this.IsRunning = false;
        }
    }

    void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if (!this.IsRunning)
            StartTask();
    }
}

using System;
using System.Data;
using System.Configuration;

public class ClassTaskScheduler
{
    ClassTask task = null;

    public ClassTaskScheduler()
    {
        this.task = new ClassTask(60000);
    }

    public void StartTask()
    {
        this.task.Start();
    }

    public void StopTask()
    {
        this.task.Stop();
    }
}

In global.asax or where you want to call this 在global.asax或您要调用的位置

void Application_Start(object sender, EventArgs e) 
    {
        // Code that runs on application startup
        ClassTaskScheduler _scheduler = new ClassTaskScheduler();
        _scheduler.StartTask();
    }

    void Application_End(object sender, EventArgs e) 
    {
        //  Code that runs on application shutdown
        ClassTaskScheduler _scheduler = new ClassTaskScheduler();
        _scheduler.StopTask();
    }

You can use Execute() function for run task in given time interval.... 您可以在给定的时间间隔内对执行任务使用Execute()函数。

The equivalent in .NET would be to use a ManualResetEvent . .NET中的等效项是使用ManualResetEvent Use the WaitOne method with a timeout to cause the waiting. WaitOne方法与超时一起使用会导致等待。 It can also double as the shutdown mechanism. 它也可以兼作关机机制。 The nice thing about this approach is that is simple, everything runs one thread, and the same code cannot be executing in parallel (because it is all on one thread). 这种方法的好处在于,它很简单,所有代码都运行在一个线程上,并且同一代码无法并行执行(因为所有代码都在一个线程上)。

class myThread
{
  private ManualResetEvent m_WaitHandle = new ManualResetEvent(false);

  public myThread
  {
    new Thread(Run).Start();
  }

  public void Shutdown()
  {
    m_WaitHandle.Set(); // Signal the wait handle.
  }

  private void Run()
  {
    while (!m_WaitHandle.WaitOne(INTERVAL)) // The waiting happens here.
    {
      // Some task
    }
    // If execution gets here then the wait handle was signaled from the Shutdown method.
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM