我有一个计时器,不需要同时处理它的已用事件处理程序。但处理一个Elapsed事件可能会干扰其他事件。我实施了以下解决方案,但感觉不对劲;似乎要么我应该使用不同的计时器,要么在线程空间内使用另一个对象。计时器似乎最合适,因为我确实需要定期检查状态,但有时检查将花费比我的间隔更长的时间。这是解决这个问题的最好方法吗?
// member variable
private static readonly object timerLock = new object();
private bool found = false;
// elsewhere
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed = Timer_OnElapsed;
timer.Start();
public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
lock(timerLock)
{
if (!found)
{
found = LookForItWhichMightTakeALongTime();
}
}
}
答案 0 :(得分:14)
您可以将AutoReset设置为false,然后在完成处理后显式重置计时器。当然,你如何处理它实际上取决于你期望计时器如何运作。这样做会使你的计时器偏离实际的指定间隔(如停止和重新启动)。您的机制将允许触发和处理每个间隔,但它可能会导致积压的未处理事件,这些事件现在在接近计时器到期时处理,导致处理程序被调用。
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed += Timer_OnElapsed;
timer.AutoReset = false;
timer.Start();
public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
if (!found)
{
found = LookForItWhichMightTakeALongTime();
}
timer.Start();
}
答案 1 :(得分:8)
我通常在处理它时停止计时器,输入一个try / finally块,并在完成时恢复计时器。
答案 2 :(得分:1)
如果LookForItWhichMightTakeALongTime()
需要花费很长时间,我建议不要使用System.Windows.Forms.Timer
,因为这样做会锁定您的UI线程,并且用户可能会认为它已冻结您的应用程序。
您可以使用的是BackgroundWorker
(如果需要,还可以使用Timer
。)
public class MyForm : Form
{
private BackgroundWorker backgroundWorker = new BackgroundWorker();
public MyForm()
{
InitializeComponents();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted +=
backgroundWorker_RunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
e.Result = LookForItWhichMightTakeALongTime();
}
private void backgroundWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
found = e.Result as MyClass;
}
}
您可以随时随地拨打RunWorkerAsync()
,如果您愿意,也可以从Timer
拨打BackgroundWorker
。并且确保检查RunWorkerAsync()
是否已经运行,因为在private void timer_Tick(object sender, EventArgs e)
{
if (!backgroundWorker.IsBusy)
backgroundWorker.RunWorkerAsync();
}
运行时会调用异常。
{{1}}
答案 3 :(得分:0)
timer.enabled = false
或
timer.stop();
和
timer.enabled = true
或
timer.start();
答案 4 :(得分:-1)
我像这样使用System.Threading.Timer
class Class1
{
static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1));
private static void DoSomething(object state)
{
timer = null; // stop timer
// do some long stuff here
timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}
}