将Threading.Timer与新的Thread()结合起来?

时间:2014-05-14 15:36:23

标签: c# .net multithreading

我有一个控制台应用程序,每小时运行一次:00。此控制台应用程序在同一小时的15:30处复制文件。

这是我的初始代码,我使用WHILE循环检查当前分钟。我想将WHILE循环替换为System.Threading.Timer

使用Threading.Timer并且不使用循环,如何在控制台应用程序启动后15分钟启动Thread0并在30分钟启动Thread1?我不想使用第三方开源解决方案。

CancellationTokenSource cts0 = new CancellationTokenSource();
CancellationTokenSource cts1 = new CancellationTokenSource();

Thread Thread0, Thread1;

DateTime TaskRunDateTime = DateTime.Now;
DateTime RightNow = DateTime.Now;

while (!thread0Running || !thread1Running)
{
    if (RightNow.Minute == 15)
    {
        thread0Running = true;
        Class myClass0 = new Class();
        Thread0 = new Thread(() => myClass0.CopyFiles(15, cts0.Token));
        Thread0.Start();
    }
    else if (RightNow.Minute == 30)
    {
        thread1Running = true;
        Class myClass1 = new Class();
        Thread1 = new Thread(() => myClass1.CopyFiles(30, cts1.Token));
        Thread1.Start();
    }
    RightNow = DateTime.Now;
}

for (; ; )
{
    fileCount = Directory.GetFiles(destPath, FileDate + "*.xml").Length;
    If (fileCount == 20)
    {  
        // All 20 files have been copied because the two threads have finished
        RunExternalReportGeneratorEXE();
        break;
    }
    else if (RightNow >= TaskRunDateTime.AddHours(2))
    {
        // Task took over 2 hours to complete. 
        // Cancel Thread0, Thread1 and run 3rd-party executable.
        cts0.Cancel();
        cts1.Cancel();
        RunExternalReportGeneratorEXE();
        break;
    }

3 个答案:

答案 0 :(得分:3)

在应用程序启动时,您可以计算X:15和X:30下降的时间。然后,您可以使用Timer的构造函数来安排计时器回调的开始时间和频率。

答案 1 :(得分:1)

创建两个可以等待的ManualResetEvent个对象。然后创建两个计时器:

ManualResetEvent Copy1Done = new ManualResetEvent(false);
ManualResetEvent Copy2Done = new ManualResetEvent(false);

Timer t1 = new Timer((s) =>
    {
        Class myClass0 = new Class();
        myClass0.CopyFiles(15, cts0.Token);
        Copy1Done.Set();
    }, null, TimeSpan.FromMinutes(15), TimeSpan.FromMilliseconds(-1));
Timer t1 = new Timer((s) =>
    {
        Class myClass1 = new Class();
        myClass0.CopyFiles(30, cts1.Token);
        Copy2Done.Set();
    }, null, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(-1));

那些是一次性计时器;它们会发射一次,然后再不发射。

现在,您需要等待两个小时才能完成副本。这就是ManualResetEvent对象进入的位置。创建一个事件数组:

WaitHandle[] handles = new WaitHandle[] {Copy1Done, Copy2Done};

// wait for both events to be signaled, or for two hours
if (!WaitHandle.WaitAll(handles, TimeSpan.FromHours(2)))
{
    // took too long. Cancel the copies.
    cts0.Cancel();
    cts1.Cancel();
    // you might want to wait here for the threads to exit.
    // otherwise you might have a problem with a locked file.
}
// and run the program
RunExternalReportGeneratorEXE();

答案 2 :(得分:0)

我不想在这里为你编写整个代码,但是为了让你知道你可以用线程计时器做什么:

void CreateTimer()
{
    // Create an event to signal the timeout count threshold in the 
    // timer callback.
    AutoResetEvent autoEvent     = new AutoResetEvent(false);
    // Create an inferred delegate that invokes methods for the timer.
    TimerCallback tcb = CheckStatus;
    // Create a timer that signals the delegate to invoke  
    // CheckStatus after 15 minutes. 
    // thereafter.
    Console.WriteLine("{0} Creating timer.\n", DateTime.Now.ToString("h:mm:ss.fff"));
    System.Threading.Timer Timer stateTimer = new Timer(tcb, autoEvent, 1000 * 60 *15, 0);
    //Wait for 15 minutes
    autoEvent.WaitOne(1000 * 60 *15, false);
    stateTimer  = new Timer(tcb, null, 1000 * 60 *30, 0);
}

// This method is called by the timer delegate. 
public void CheckStatus(Object stateInfo)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), stateInfo);
}

public void DoWork(Object stateInfo)
{
    AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
    autoEvent.Set();
    //Change your worktype here.
    CancellationTokenSource cts0 = new CancellationTokenSource();
    Class myClass1 = new Class();
    myClass1.CopyFiles(30, cts0.Token);

}