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循环内循环完成,不知何故该方法运行不了一分钟?有什么帮助吗?
答案 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();
}
}
}