c#:在循环前设置定时器,定时器持续2分钟后中断循环
我对C#很陌生,而且我以前从未使用过计时器。 我想在while循环中运行一段代码150秒。我的想法是在while循环之前设置一个计时器,该计时器将在150秒后关闭。我已经设置了一个默认为false的布尔exitFlag,当计时器关闭时,它会将其设置为truec#:在循环前设置定时器,定时器持续2分钟后中断循环,c#,timer,C#,Timer,我对C#很陌生,而且我以前从未使用过计时器。 我想在while循环中运行一段代码150秒。我的想法是在while循环之前设置一个计时器,该计时器将在150秒后关闭。我已经设置了一个默认为false的布尔exitFlag,当计时器关闭时,它会将其设置为true public static System.Timers.Timer DL_stuckTimer; static int secondleft = 150 ; static bool exitFlag = false; public st
public static System.Timers.Timer DL_stuckTimer;
static int secondleft = 150 ;
static bool exitFlag = false;
public static void SetTimer()
{
// Create a timer with a two second interval.
DL_stuckTimer = new System.Timers.Timer(2000); //tick every 2 second
// Hook up the Elapsed event for the timer.
DL_stuckTimer.Elapsed += DL_stuckTimerEvent;
DL_stuckTimer.AutoReset = true;
DL_stuckTimer.Enabled = true;
}
/*** Timer that goes off after 2.5 second and will tell the down
**/
public static void DL_stuckTimerEvent(Object myObject, EventArgs myEventArgs)
{
if (secondleft == 0)
{
DL_stuckTimer.Stop();
exitFlag = true;
}
secondleft -= 2;
}
SetTimer();
do{
//some code here
} while (!exitFlag);
这不管用。我做错了什么。看起来计时器根本就不会启动。我会使用
取消令牌而不是计时器来执行此操作
然后,您可以创建一个CancellationTokenSource
,它将在指定时间后自动取消
在循环内部,您将检查CancellationToken.IsCancellationRequested
,而不是检查退出标志
完整的可编译控制台应用程序示例如下所示:
using System;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var cancellationSource = new CancellationTokenSource(TimeSpan.FromSeconds(150));
Console.WriteLine("Started at time " + DateTime.Now);
SomeMethod(cancellationSource.Token);
Console.WriteLine("Finiehd at time " + DateTime.Now);
}
static void SomeMethod(CancellationToken cancellation)
{
do
{
Thread.Sleep(10); // Some code goes here.
}
while (!cancellation.IsCancellationRequested);
}
}
}
这样做的一个优点是,它是基于任务的取消的工作方式,如果您想以另一种方式取消,您可以传递其他类型的取消令牌
您还可以更改忙循环,使其仅每隔500毫秒执行一次操作,但在发出取消令牌信号时仍将尽快退出循环
要做到这一点,您将使用CancellationToken.WaitOne()
方法,如下所示:
static void SomeMethod(CancellationToken cancellation)
{
do
{
// Do something every 500 ms.
}
while (!cancellation.WaitHandle.WaitOne(500)); // Wait up 500ms, but return immediatly if signalled.
}
正如亚历山德罗所提到的,你可以用秒表代替:
public static void Main()
{
var sw = new Stopwatch();
sw.Start();
while(sw.ElapsedMilliseconds < 150000)
{
//Do stuff for 150 seconds.
Thread.Sleep(2000); //Wait 2 seconds before the next iteration/tick.
}
sw.Stop(); //150 seconds is over.
}
publicstaticvoidmain()
{
var sw=新秒表();
sw.Start();
同时(sw.ElapsedMilliseconds<150000)
{
//做150秒的动作。
Thread.Sleep(2000);//在下一次迭代之前等待2秒/tick。
}
sw.Stop();//150秒结束。
}
让我们从实际问题开始:似乎您想要执行一个较长的过程,如果尚未完成,您希望在2分钟后终止该过程。
这类问题可以通过Task
s解决:
using System.Threading;
using System.Threading.Tasks;
...
// 2 minutes = 2 * 60 * 1000 milliseconds
using (CancellationTokenSource cts = new CancellationTokenSource(2 * 60 * 1000)) {
CancellationToken token = cts.Token;
try {
Task task = Task.Run(() => {
//TODO: put relevant code here
...
// Cancellation is a cooperative, that's why do not forget to check the token
token.ThrowIfCancellationRequested();
...
},
token);
await task;
}
catch (TaskCanceledException) {
// Task has been cancelled due to timeout
//TODO: put relevant code here
}
}
改为使用并检查属性以查看经过了多少秒。您的代码按原样为我工作!不过,您不需要exitFlag,只需检查secondLeft>0
谢谢Alessandro。为什么我需要在代码中添加Thread.Sleep(2000)?谢谢。了解CancellationToken的存在是件好事。我打算选择秒表