运行并停止一分钟的方法

时间:2013-07-05 19:23:47

标签: c# .net winforms timer

timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Start();
MyMethodName();
timer1.Stop();

MyMethodName()

- 有一个90,000个条目的for循环(以及for循环中的一些验证)。

for (int i = 0; i <= 90000; i++)
{
 //validations go here

}

当timer1中的时间完成一分钟后,我想停止执行for循环中的其他条目。 例如,如果一分钟内完成45,000个条目,我想停止执行该方法,即。一分钟后停止方法。

然而上面的定时器代码执行直到所有90000记录都在for循环内循环完成,不知何故该方法运行不了一分钟?有什么帮助吗?

6 个答案:

答案 0 :(得分:2)

两件事。首先,您的计时器代码实际上并未连接到MyMethodName的运行。计时器设计用于在时间结束后运行进程(并且可能定期运行,具体取决于它的设置方式。

其次,更重要的是你的问题要中止一个循环,你必须把代码放在循环中。关键是在你的循环之前有一个秒表或类似的开始,然后在你的循环开始时检查已经过了多少时间。如果是一分钟或更长时间,则为break;

需要注意的关键是你不会在一分钟内完全停止,但是你将完成当分钟到期然后停止时运行的循环的迭代。这通常是你想要的,因为在中途停止处理可能会导致令人讨厌的副作用。

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i =0; i<=90000; i++)
{
    if (stopwatch.Elapsed>TimeSpan.FromSeconds(5))
        break;
    Console.WriteLine(i);
    Thread.Sleep(1000);
}

请注意,Thread.Sleep只是因为否则我太快完成了所有90000次迭代。 ; - )

答案 1 :(得分:2)

所以你可能需要一个非常不同的实现。考虑一下:

public class MyForm
{
    private BackgroundWorker _worker;

    public MyForm()
    {
        _worker = new BackgroundWorker();
        _worker.DoWork += (s, args) =>
        {
            var timer = Stopwatch().StartNew();
            do
            {
                // do something
            } while (timer.ElapsedMilliseconds < 60000)
        };
    }
}

然后当你想要运行它时:

_worker.RunWorkerAsync();

然而,你可以使它更强大。你可以像这样传递时间:

_worker.RunWorkerAsync(60000);

然后在DoWork处理程序中执行此操作:

while (timer.ElapsedMilliseconds < (int)args.Argument)

此外,使用BackgroundWorker,您可以支持取消。只需将WorkerSupportsCancellation标记设置为true,然后在条件下执行以下操作:

while (timer.ElapsedMilliseconds < (int)args.Argument && !_worker.CancellationPending)

所以,如果有必要,你可以这样做:

_worker.CancelAsync();

答案 2 :(得分:1)

嗯,请改用秒表

  Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();


for(int i= 0; i <= 90000; i++)
{
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

if(ts.Seconds >= 60)
  break;

}

答案 3 :(得分:1)

  

然而上面的定时器代码执行直到所有90000记录都在for循环内循环完成,不知何故该方法运行不了一分钟?有什么帮助吗?

在释放UI线程之前,计时器不会引发事件,直到方法完全完成后才会发生。

如果您想阻止该方法运行超过特定的持续时间,您可以直接在您的方法中处理它:

MyMethodName(TimeSpan.FromMinutes(1));

然后,在你的方法中:

void MyMethodName(TimeSpan maxRuntime)
{
    DateTime expiration = DateTime.Now + maxRuntime;

    for (int i = 0; i <= 90000; i++)
    {
         //validations go here

         if (i % 100 == 0) //  check every 100?
         {
              if (DateTime.Now > expiration) 
                    break;
         }
    }
}

话虽如此,更好的方法是将其推入后台线程,并根据需要取消。

答案 4 :(得分:0)

你可以在验证中设置一个标志,通过将一个事件处理程序连接到Timer对象中的Tick事件来查看它是否已完成

//in an area accessible to 
//both elements
object readonly _lock = new object();
bool elapsed = false;

您原始代码的位置

elapsed = false;
timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Tick=((sender, everntArgs)=>
{
    lock(_lock)
        elapsed = true; 
});
timer1.Start();
MyMethodName();
timer1.Stop();

MyMethodName

//inside the loop
for (int i = 0; i <= 90000; i++)
{
    //validations go here
    lock(_lock)
        if(elapsed)
            break;
}

答案 5 :(得分:0)

如果对CancellationTokenSource(TimeSpan)构造函数使用CancellationTokenSource,则可以轻松编写一个在指定时间后取消操作的方法。

您可以编写如下方法:

public static void RunTimedAction(Action<CancellationToken> action, TimeSpan timeout)
{
    using (var cancellationTokenSource = new CancellationTokenSource(timeout))
        action(cancellationTokenSource.Token);
}

然后你可以编写任何以CancellationToken为参数的动作,如下所示:

private void action(CancellationToken cancel)
{
    int i;

    for (i = 0; i < 1000000; ++i)
    {
        if (cancel.IsCancellationRequested)
            break;

        Thread.Sleep(10); // Simulate work.
    }

    Console.WriteLine("action() reached " + i);
}

您可以这样使用:

Console.WriteLine("Started at " + DateTime.Now);

RunTimedAction(action, TimeSpan.FromSeconds(10));

Console.WriteLine("Stopped at " + DateTime.Now);

让我们将它们整合到一个完整的演示程序中:

using System;
using System.Threading;

namespace Demo
{
    class Program
    {
        void run()
        {
            Console.WriteLine("Started at " + DateTime.Now);

            RunTimedAction(action, TimeSpan.FromSeconds(10));

            Console.WriteLine("Stopped at " + DateTime.Now);
        }

        private void action(CancellationToken cancel)
        {
            int i;

            for (i = 0; i < 1000000; ++i)
            {
                if (cancel.IsCancellationRequested)
                    break;

                Thread.Sleep(10); // Simulate work.
            }

            Console.WriteLine("action() reached " + i);
        }

        public static void RunTimedAction(Action<CancellationToken> action, TimeSpan timeout)
        {
            using (var cancellationTokenSource = new CancellationTokenSource(timeout))
                action(cancellationTokenSource.Token);
        }

        static void Main()
        {
            new Program().run();
        }
    }
}