c#:在循环前设置定时器,定时器持续2分钟后中断循环

c#:在循环前设置定时器,定时器持续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

我对C#很陌生,而且我以前从未使用过计时器。 我想在while循环中运行一段代码150秒。我的想法是在while循环之前设置一个计时器,该计时器将在150秒后关闭。我已经设置了一个默认为false的布尔exitFlag,当计时器关闭时,它会将其设置为true

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的存在是件好事。我打算选择秒表