Windows 我如何等待工作进程完成,但又如何限制它';是时候这么做了?

Windows 我如何等待工作进程完成,但又如何限制它';是时候这么做了?,windows,vb.net,service,Windows,Vb.net,Service,我正在用VB.Net编写一个Windows服务,它将输出一些设备和数据记录点的信息。我正在使用后台工作人员来完成这项工作,因此服务本身仍然能够响应。我有一个计时器,每秒钟运行一次,检查当前时间的分钟部分。每次分钟组件更改时,我都会检查需要检查的设备,有些是每分钟检查一次,有些是每5分钟检查一次,有些是每10分钟检查一次,等等。这些过程可能需要几秒钟或一分钟以上(我只会在辅助进程尚未运行时重新运行辅助进程,如果最后一个进程的时间长于数据检索间隔时记录错误) 在我为该服务举办的现场活动中,我希望确保

我正在用VB.Net编写一个Windows服务,它将输出一些设备和数据记录点的信息。我正在使用后台工作人员来完成这项工作,因此服务本身仍然能够响应。我有一个计时器,每秒钟运行一次,检查当前时间的分钟部分。每次分钟组件更改时,我都会检查需要检查的设备,有些是每分钟检查一次,有些是每5分钟检查一次,有些是每10分钟检查一次,等等。这些过程可能需要几秒钟或一分钟以上(我只会在辅助进程尚未运行时重新运行辅助进程,如果最后一个进程的时间长于数据检索间隔时记录错误)

在我为该服务举办的现场活动中,我希望确保所有工人都停工。我在worker上调用CancelAsync,worker检查取消,希望能够干净地退出(即,检查取消,如果为false,则检索数据,将数据保存到数据库中,循环)

我的问题是我不想使用sleep语句,因为它会锁定所有内容,但我也不希望服务永远不会关闭。例如,我现在有:

Protected Overrides Sub OnStop()
    ' Add code here to perform any tear-down necessary to stop your service.
    My.Application.Log.WriteEntry("ServiceABC shutting down for device " & DeviceID)
    ServiceTimer.enable = false
    If DataRetrievalBackgroundWorker.IsBusy Then
        DataRetrievalBackgroundWorker.CancelAsync()
        Dim x As Integer = 0
        While ((DataRetrievalBackgroundWorker.IsBusy) Or (x < 15))
            Threading.Thread.Sleep(1000)
            x += 1
        End While
    End If
End Sub
protectedoverrides子桌面()
'在此处添加代码以执行停止服务所需的任何拆卸。
My.Application.Log.WriteEntry(“为设备关闭ServiceC”&DeviceID)
ServiceTimer.enable=false
如果DataRetrievalBackgroundWorker.IsBusy,则
DataRetrievalBackgroundWorker.CancelAsync()
尺寸x为整数=0
While((DataRetrievalBackgroundWorker.IsBusy)或(x<15))
线程。线程。睡眠(1000)
x+=1
结束时
如果结束
端接头

因为后台工作线程位于另一个线程上,所以应该可以这样做,对吗?有没有更好的方法来处理这个问题?

你很接近了,如果你不想睡觉(1000)并把东西锁起来,那就睡一觉(1)

'尺寸x为整数=0
'而((DataRetrievalBackgroundWorker.IsBusy)或(x<15))
'线程。线程。睡眠(1000)
'x+=1
"结束!
Dim T As Date=Now.ADDSECONES(15)
当DataRetrievalBackgroundWorker.IsBusy或Now()时
线程。线程。睡眠(1)
Application.DoEvents()
结束时

使用任务而不是BackGroundWorker,等待它,传递带有超时设置的CancellationToken及其CancellationTokenSource。
ReportProgress
过程被替换为传递几乎相同的
Progress
委托并调用其
Report()
方法。如果需要,可以在
Task
T
对象中返回完成结果。我以前从未使用过任务,但我会看看我能找到什么。这里有一些不同的示例:。了解当前在
DoWork
处理程序中执行的操作类型、是否调用
ReportProgress()
以及BGW终止时使用的数据和发生的情况(即,如果在
RunWorkerCompleted
中执行其他操作),这一点非常重要。一般来说,如果您正在执行IO绑定工作或CPU绑定工作,那么当前的BGW将转到URL,获取数据,并将其插入SQL数据库。它在一个广泛的URL列表中循环,有时可达2k,但检索到的数据很小(20个字符左右)。它目前不支持
ReportProgress
RunWorkerCompleted
中唯一的一个变量是一个用日期更新的last run变量。现在,我可以跟踪它运行的时间。因此,IO绑定,它也支持异步/等待模式,因为您有所有可等待的方法。不清楚您正在使用下载的数据做什么。只需更新数据库,全部在
DoWork
处理程序中?数据库更新也是(通常)可等待的(例如,
SqlCommand.ExecuteReaderAsync()
SqlCommand.ExecuteNonQueryAsync(()
等),并且具有接受CancellationToken的重载(因此,隐式地,也是一个超时,因为这是由创建CancellationToken的CancellationTokenSource设置的)是的,我想我也可以这样做。真正的问题是,如果我在实际工作中使用背景工作人员,这是否重要……睡眠(1000次)“不应该”阻止它完成,因为它是在自己的线程上,对吗?另一个选项是查看@Jimi发布的任务,我仍在试图弄清楚。我忘记添加DoEvents…是的,后台工作人员无论如何都不会被阻止。我不喜欢任务,一旦你执行任务,你就不能返回。我可以将sub转换为线程并调用它不管怎样,我想。你不能用任务来做。一旦子任务是一项任务,它就只是一项任务。
    'Dim x As Integer = 0
    'While ((DataRetrievalBackgroundWorker.IsBusy) Or (x < 15))
    '    Threading.Thread.Sleep(1000)
    '    x += 1
    'End While

    Dim T As Date = Now.AddSeconds(15)
    While DataRetrievalBackgroundWorker.IsBusy Or Now() < T
        Threading.Thread.Sleep(1)
        Application.DoEvents()
    End While