【发布时间】:2012-01-30 11:40:26
【问题描述】:
我有一个BackgroundWorker,它创建了一个计时器。计时器重复调用DataTable。我只希望在计时器停止时调用BackgroundWorker.RunWorkerCompleted 事件。我该怎么做?
谢谢。
【问题讨论】:
标签: c# timer backgroundworker
我有一个BackgroundWorker,它创建了一个计时器。计时器重复调用DataTable。我只希望在计时器停止时调用BackgroundWorker.RunWorkerCompleted 事件。我该怎么做?
谢谢。
【问题讨论】:
标签: c# timer backgroundworker
只需在BackgroundWorker 的DoWork 事件处理程序中创建一个循环并重复循环直到计时器停止。或多或少是这样的:
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
var timer = new Timer();
timer.Elapsed += (s, _e) =>
{
// call the database
};
timer.Start();
while (timer.Enabled)
{
// at some point: timer.Stop();
}
// if we are here, timer is no longer Enabled
// RunWorkerCompleted event will be fired next
};
(显然我忽略了设置计时器的Interval 等)
【讨论】:
Elapsed 事件处理程序中禁用自身,例如基于从它进行的数据库调用中检索到的数据(或缺少数据)。但这是一个有效的观点;当然,如果您需要从外部访问计时器,则应在其他地方声明计时器。此外,lambdas 并不总是最好的选择。我的代码只是一个 sn-p,旨在提供一个想法的图片。
BackGroundWorker.RunWorkerCompleted 在您的 DoWork 事件完成后调用。因此,如果您确保 DoWork 事件完成,您的 RunWorkerCompleted 事件应该由后台工作人员调用。
另一种解决方案是在后台工作人员之外创建计时器,并通过计时器控制后台工作人员实例。在计时器事件中,检查 IsBusy 属性是否设置为 false 并启动后台工作程序,如果 IsBusy 为 true,则跳过。
示例:
_worker.DoWork += (sender, e) =>
{
BackgroundWorker worker = sender as BackgroundWorker;
// Do your database stuff
e.Result = databaseResult;
}
_timer.Elapsed += (source, e) =>
{
if(!_worker.IsBusy)
{
_worker.RunWorkerAsync();
}
}
【讨论】: