我有一个控制台应用程序,每小时运行一次: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;
}
答案 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);
}