C# 每 X 分钟运行一个线程,但前提是该线程尚未运行

2024-01-10

我有一个 C# 程序,需要每 X 分钟调度一个线程,但前提是之前调度的线程(从 X 分钟开始)当前尚未运行.

一个普通的老Timer单独运行是行不通的(因为它每 X 分钟调度一个事件,无论先前调度的进程是否已完成)。

将要分派的进程执行其任务所需的时间差异很大 - 有时可能需要一秒钟,有时可能需要几个小时。如果该进程仍在上次启动时处理,我不想再次启动该进程。

谁能提供一些有效的 C# 示例代码?


在我看来,在这种情况下要走的路是使用System.ComponentModel.BackgroundWorker类,然后简单地检查它的IsBusy每次您想要分派(或不分派)新线程时。代码非常简单;这是一个例子:

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该类还支持进度报告和取消,并使用事件驱动模型与调度线程进行通信,因此您不必担心易失性变量等...

EDIT

这是更详细的示例,包括取消和进度报告:

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()。请注意,这是完全由用户处理的取消机制(它不支持线程中止或类似的开箱即用的机制)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 每 X 分钟运行一个线程,但前提是该线程尚未运行 的相关文章

随机推荐