C# 在这种情况下使用线程?

C# 在这种情况下使用线程?,c#,multithreading,C#,Multithreading,我有一种方法,基本上是将文件从远程系统复制到本地系统。此方法需要在一小时内执行4次,每15分钟执行一次。调用该方法时使用Period作为参数,其中Period的范围为0-3(0=Min:0-15;3=Min:45-0) 如何将这些线程作为单独的线程运行,然后在下一个小时之前停止所有线程:20,以便调用外部程序ProcessFiles.EXE?我总是可以继续执行线程,但我不知道读取文件的程序的线程安全性如何。所以我更喜欢在下一个20之前把所有的线都剪断 以前,15分钟的时间窗口足以复制15分钟内的

我有一种方法,基本上是将文件从远程系统复制到本地系统。此方法需要在一小时内执行4次,每15分钟执行一次。调用该方法时使用Period作为参数,其中Period的范围为0-3(0=Min:0-15;3=Min:45-0)

如何将这些线程作为单独的线程运行,然后在下一个小时之前停止所有线程:20,以便调用外部程序ProcessFiles.EXE?我总是可以继续执行线程,但我不知道读取文件的程序的线程安全性如何。所以我更喜欢在下一个20之前把所有的线都剪断

以前,15分钟的时间窗口足以复制15分钟内的所有文件。不幸的是,这一进程变得非常缓慢。因此,假设我正在运行第一个IF语句(在:20),而不是在到达第35分钟时停止它,我可以让它在线程中运行,直到一小时结束。但是,如果在next:20之后还没有完成,那么线程需要停止

编辑:它以前在任务计划程序中。该任务将在15分钟内复制20个文件。不幸的是,文件复制变得非常慢。所以现在,在某些块中,文件拷贝需要15分钟多一点

所以我最初的想法是对这些过程进行线程化。在第一个15分钟块的情况下(在分钟20中运行的IF语句将文件从Min.00复制到Min.1),假设我使用了一个线程。这意味着,即使在第35分钟之前(复制过程从第15分钟到第30分钟开始)没有完成,它仍然要等到下一次迭代的第20分钟(循环的第一个if语句)

调度器的缺点是,如果任务没有按时完成,它将1)阻止调度器再次运行任务,或者2)如果我强制它关闭,则只复制要复制的部分内容

这是我的一些代码,因此您对我的工作有了一个概念:

public static void Main(string[] args)
{
    DateTime DateNow = new DateTime(2014, 3, 1, 5, 0, 0); //For the example, start at 5AM.
    Thread thread0 ;
    Thread thread1 ;
    Thread thread2 ;
    Thread thread3 ;
    for (; ; ) //infinite loop
    {
        //DateNow will usually be DateTime.Now.
        if (DateNow.Minute == 20)
        {
            //Copy files from 5:00-5:15.
            //IF any of the threads from Hour 4 are still running, they must be stopped
            _CurrentHour = DateNow.Hour;
            thread0 = new Thread(() => CopyFiles(_CurrentHour, 0));
            thread0.Start();
        }
        else if (DateNow.Minute == 35)
        {
            //Copy files from 5:15-5:30.
            thread1 = new Thread(() => CopyFiles(_CurrentHour, 1));
            thread1.Start();
        }
        else if (DateNow.Minute == 50)
        {
            //Copy files from 5:30-5:45.
            thread2 = new Thread(() => CopyFiles(_CurrentHour, 2));
            thread2.Start();
        }
        else if (DateNow.Minute == 5)
        {
            //Copy files from 5:45-6:00.
            thread3 = new Thread(() => CopyFiles(_CurrentHour, 3));
            thread3.Start();
        }
        thread0.Join(); 
        thread1.Join();
        thread2.Join();
        thread3.Join();
        //CALL ProcessFiles.EXE

    }       
}

在第一个线程中,等待15分钟,然后复制文件:

System.Threading.Thread.Sleep(1000 * 60 * 15); // 15 mins
如果要终止线程,可以调用Abort函数:

thread1.Abort();

看起来你在寻找两样东西

  • 周期计时器。这些都来自.NET。您可以将计时器安排为每15分钟执行一次,并根据每季度或每小时执行一次,决定要复制哪些文件

  • 将要在工作线程上执行的工作单元排队。同样,这里您有多种选择,从使用托管线程池(直接通过)或通过(更容易),或滚动您自己的线程池(类似于您尝试做的更复杂但更适合长时间运行的任务)


  • 为了解决其他问题,关于在15分钟窗口内停止工作线程,最好的选择是让工作线程负责这一点。当定时器被触发时,您应该记录文件操作的开始时间,并在工作线程中定期检查运行时间是否小于所需的长度(15分钟)。如果线程检测到它接近极限,它应该优雅地停止它的处理,也许,通知你的应用程序或系统的其余部分关于它没有完成的事实。

    < P>你可以考虑使用任务和取消令牌。


    通过这种方式,您可以取消任务,然后轮询任务,直到任务完成/取消,然后再继续下一步。

    其他程序是否是另一个程序?跨进程线程同步是非常重要的。“其他东西”是另一个程序。难道你没有得到
    NullReferenceException
    ?很难相信。这听起来更适合默认的Windows任务调度程序,其中包括在以前的迭代运行时间过长时终止它们,并在完成时启动其他任务。不要白费力气,但是任务调度器包括每天每15分钟运行一次的功能,以及在1小时后自动终止。thread.Abort()是一个非常糟糕的主意。线程终止应该是合作的。
    Sleep()
    也不是完全可靠的-可能不到15分钟,不管线程请求什么。我最终使用了取消令牌。