我的第一个非异步尝试是使用计时器每15秒调用一次该进程。这样很快就创建了多个运行的进程,这些启动了数据库上的争用条件,因为根据队列的大小,函数_myApp.ProcessQueue();
可能需要5到10分钟才能运行。这实际上锁定了数据库,因为它试图读取和写入相同的行。如果我增加计时器,可以防止发生竞争状况的可能性,但是我认为这不是一种非常实用的服务方式。
protected override void OnStart(string[] args)
{
_log.Info($"Service is started at {DateTime.Now}.");
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 15000;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
int recCount = _dbHandler.CheckQueueCount();
if (recCount > 0)
{
_log.Info($"Found {recCount} records in the queue.");
try
{
_myApp.ProcessQueue();
}
catch (Exception exception)
{
_log.Error(exception);
Stop();
}
}
}
我正在考虑解决此问题的方法是使用异步函数,但是由于以前从未使用过.Net的异步功能,因此我很难编写它。
答案 0 :(得分:0)
使用OnStart()
在另一个线程(Task.Run()
或如果必须调整某些参数Task.Factory.Start()
)中初始化运行器,以在短时间内正确返回该方法。
如果我对您的理解正确,那么您一次只想处理一项工作,然后再处理下一项,对吗?
我的示例包括始终等待额外的15秒。如果您不希望这样做,则必须稍微调整一下代码。
没有异步/等待状态
要使循环与作业处理同步,可以在另一个线程中启动作业(请参见上文),并使用AutoResetEvent
。在您的循环中,您将等待_autoResetEvent.WaitOne()
,一旦完成工作,您就可以用_autoResetEvent.Set()
发出信号通知另一个线程继续执行。
使用合适的东西来等待15秒钟,例如Thread.Sleep()
使用异步/等待 这要容易得多,您只需要等待任务调用即可。
await Task.Run(() => MyJobMethod(argA, argB, ...));
await Task.Delay(15000);