我有一个Windows窗体应用程序,它从多个设备收集数据 - 并将该数据存储在本地SQLite数据库中。然后,在一段时间内,我需要将新记录上传到外部Web服务 - 这意味着我需要使用“WasUploaded = 0”字段读取新记录,上传它们,然后在成功时设置“WasUploaded = 1”。今天我会像10年前那样做同样的事情 - 分叉一个新的背景线程,做无穷无尽的循环:
while(true)
{
try
{
var newRecords = dbRepo.ReadNew(10); // read 10 records at a time
UploadToExternalWebservice(newRecords);
foreach (var r in newRecords)
{
r.WasUploaded = 1;
}
dbRepo.CommitChanges(newRecords);
}
catch (Exception ex)
{
Logger.LogError(ex);
}
Thread.Current.Sleep(15*1000);
}
但我开始怀疑 - 有没有更好的方法可以做到这一点?是否值得在这里使用任务库?还有其他什么?
如果重要的话我在.Net 4.0上。
谢谢。
答案 0 :(得分:1)
使用计时器。每10分钟(或其他)设置一次,然后上传。
System.Threading.Timer uploadTimer = new Timer(UploadProc, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
void UploadProc(object state)
{
// do query, upload, and update logic here
}
不需要花费大部分时间睡觉的显式线程。
如果你想要它更频繁(在你的例子中你有15秒),你会遇到重入计时器滴答的可能性。也就是说,如果你将它设置为15秒并且处理时间超过15秒,那么你最终将会有多个线程同时运行上传代码。
如果有可能,您有两种选择:使用锁定来防止重入,或使用您在每个过程后更新的一次性计时器。
锁很简单。在类范围定义一个锁对象:
private object uploadLock = new object();
在UploadProc中:
void UploadProc(object state)
{
if (!Monitor.TryEnter(uploadLock))
{
// upload in progress. Quit.
return;
}
try
{
// processing here
}
finally
{
Monitor.Exit(uploadLock);
}
}
效果很好。一次性的想法包括将计时器设置为勾选一次然后停止。然后在完成处理后更新它:
System.Threading.Timer uploadTimer = new Timer(
UploadProc, null, TimeSpan.FromSeconds(15), TimeSpan.FromMilliseconds(-1));
void UploadProc(object state)
{
// processing here
// now reset the timer
uploadTimer.Change(TimeSpan.FromSeconds(15), TimeSpan.FromMilliseconds(-1));
}
答案 1 :(得分:0)
这是一个基本的推拉拉问题。如果数据源可以通知您,那么您可以这样做,但我认为您的方法是正确的。您可以设置提取这些数据的不同服务。
答案 2 :(得分:0)
答案 3 :(得分:0)
我已经使用了DispatcherTimer
类。
使用示例:
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromSeconds(1);
dt.Tick += delegate(object s, EventArgs args) {
//Your Logic here!!
};
timer.Start();
这里也是班级:DispatcherTimer