在这种情况下使用线程?

时间:2014-05-07 19:22:46

标签: c# multithreading

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

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

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

编辑:以前是在任务计划程序中。该任务将复制20个文件,分别为15分钟的时间范围。不幸的是,文件复制变得非常慢。所以现在,在某些块中,文件副本花费的时间超过15分钟。

所以我最初的想法就是对这些过程进行处理。如果是第1个15分钟的块(在分钟20 中运行的IF语句将文件从Min.00复制到Min.1),请说我使用了一个线程。这意味着,即使没有完成 Minute 35 (其中复制过程的时间为Min.15-Min.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

    }       
}

3 个答案:

答案 0 :(得分:2)

看起来你正在寻找两件事。

  1. 定期计时器。这些来自multiple flavors中的.NET。您可以将计时器安排为每15分钟执行一次,具体取决于它在哪个季度或小时,您可以决定要复制哪些文件。

  2. 将一个工作单元排队以在工作线程上执行。在这里你有多个选项,从使用托管线程池(直接通过ThreadPool API)或通过Task API(更容易),或自己滚动(类似于你尝试做的更多,更多)复杂但更适合长期运行的任务)

  3. 为解决您的其他问题,关于在15分钟窗口内停止工作线程,最好的选择是使其成为工作线程的责任。您应该在触发计时器时记录文件操作的开始时间,并在工作线程中定期检查经过的时间是否小于所需的长度(15分钟)。如果线程检测到它接近极限,它应该优雅地停止其处理,并且可能通知应用程序或系统的其余部分它未完成的事实。

答案 1 :(得分:1)

您可以考虑使用任务和取消令牌。

http://msdn.microsoft.com/en-us/library/dd537607(v=vs.110).aspx

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

答案 2 :(得分:-2)

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

System.Threading.Thread.Sleep(1000 * 60 * 15); // 15 mins

如果要杀死该线程,可以调用Abort函数:

thread1.Abort();