C#运行每X分钟一个线程,但只有当该线程尚未运行 [英] C# run a thread every X minutes, but only if that thread is not running already

查看:93
本文介绍了C#运行每X分钟一个线程,但只有当该线程尚未运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要派遣一个线程每隔X分钟C#程序,的但只有当先前派出的线程(从X分钟)前是不是目前仍在运行的的。

I have a C# program that needs to dispatch a thread every X minutes, but only if the previously dispatched thread (from X minutes) ago is not currently still running.

一个普通的老式定时单独将无法正常工作(因为它发送一个事件每隔X分钟不分或者与否。先前派遣过程完成尚未)

A plain old Timer alone will not work (because it dispatches an event every X minutes regardless or whether or not the previously dispatched process has finished yet).

这会得到调度的过程撒野它需要执行它的任务所需的时间而变化 - 有时它可能需要一秒钟,有时可能需要几个小时。我不想再次启动过程中,如果它仍然从它开始最后一次处理。

The process that's going to get dispatched varies wildly in the time it takes to perform it's task - sometimes it might take a second, sometimes it might take several hours. I don't want to start the process again if it's still processing from the last time it was started.

任何人都可以提供一些工作C#示例代码?

Can anyone provide some working C# sample code?

推荐答案

在我认为在这种情况下要走的路是用 System.ComponentModel.BackgroundWorker 类,然后简单地检查它的 IsBusy 要派遣(或没有)的新线程每次财产。该代码非常简单;这里有一个例子:

In my opinion the way to go in this situation is to use System.ComponentModel.BackgroundWorker class and then simply check its IsBusy property each time you want to dispatch (or not) the new thread. The code is pretty simple; here's an example:

class MyClass
{    
    private BackgroundWorker worker;

    public MyClass()
    {
        worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        Timer timer = new Timer(1000);
        timer.Elapsed += timer_Elapsed;
        timer.Start();
    }

    void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if(!worker.IsBusy)
            worker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //whatever You want the background thread to do...
    }
}

在这个例子中我使用 System.Timers.Timer ,但我相信它也应与其他计时器工作。在的BackgroundWorker 类还支持进展的报告和取消,并使用通信的事件驱动模型与调度线程,因此您不必担心volatile变量之类的...

In this example I used System.Timers.Timer, but I believe it should also work with other timers. The BackgroundWorker class also supports progress reporting and cancellation, and uses event-driven model of communication with the dispatching thread, so you don't have to worry about volatile variables and the like...

修改

下面是更复杂的例子包括取消和进度报告

Here's more elaborate example including cancelling and progress reporting:

class MyClass
{    
    private BackgroundWorker worker;

    public MyClass()
    {
        worker = new BackgroundWorker()
        {
            WorkerSupportsCancellation = true,
            WorkerReportsProgress = true
        };
        worker.DoWork += worker_DoWork;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;

        Timer timer = new Timer(1000);
        timer.Elapsed += timer_Elapsed;
        timer.Start();
    }

    void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if(!worker.IsBusy)
            worker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker w = (BackgroundWorker)sender;

        while(/*condition*/)
        {
            //check if cancellation was requested
            if(w.CancellationPending)
            {
                //take any necessary action upon cancelling (rollback, etc.)

                //notify the RunWorkerCompleted event handler
                //that the operation was cancelled
                e.Cancel = true; 
                return;
            }

            //report progress; this method has an overload which can also take
            //custom object (usually representing state) as an argument
            w.ReportProgress(/*percentage*/);

            //do whatever You want the background thread to do...
        }
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        //display the progress using e.ProgressPercentage and/or e.UserState
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if(e.Cancelled)
        {
            //do something
        }
        else
        {
            //do something else
        }
    }
}

然后,为了简单地取消进一步执行叫 worker.CancelAsync()。注意,这是完全由用户处理取消机制(它不支持线程中止或类似的东西超出了盒)。

Then, in order to cancel further execution simply call worker.CancelAsync(). Note that this is completely user-handled cancellation mechanism (it does not support thread aborting or anything like that out-of-the-box).

这篇关于C#运行每X分钟一个线程,但只有当该线程尚未运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆