【发布时间】:2018-04-03 07:28:39
【问题描述】:
我的班级监视传入文件的目录。它确实使用FileSystemWatcher 对象执行此操作,仅监视FSW 的Created 事件。
在Created 事件中,我开始了一个可能很耗时的过程(需要文件反序列化,使用我的类向客户端发送一个事件,其中可能会发生各种事情)。因此,我启动了一个 BackgroundWorker 对象来完成所有这些工作,最终将接收到的文件删除。
但是,在所有这些工作期间,可能会出现新文件。在Created 事件中,我检查BGW 是否仍然忙,如果是,我只需将完全限定名称存储在队列中以供以后使用。
Public Sub New(Path As String)
FSM = New FileSystemWatcher
With FSW
.Path = Path
AddHandler .Created, AddressOf pFileArrived
End With
BGW = New BackgroundWorker
With BGW
.WorkerReportsProgress = False
.WorkerSupportsCancellation = False
AddHandler .DoWork, AddressOf BGW_DoWork
AddHandler .RunWorkerCompleted,
AddressOf BGW_RunWorkerCompleted
End With
End Sub
Private Sub pFileArrived(sender As Object, e As FileSystemEventArgs)
pNotifyClient(e.FullPath)
End Sub
Private Sub pNotifyClient(sFullPath As String)
If Not BGW.IsBusy Then
BGW.RunWorkerAsync(sFullPath)
Else
MyQueue.Enqueue(sFullPath)
End If
End Sub
Private Sub BGW_DoWork(ByVal sender As Object,
ByVal e As DoWorkEventArgs)
'...
End Sub
但是我怎样才能知道BGW 何时完成?
我知道,有 RunWorkerCompleted 事件。然而,这个事件是从一个仍然存在的真实的BGW 实例触发的,所以我不能继续简单地从事件处理程序中再次调用它。
Private Sub BGW_RunWorkerCompleted(sender As Object,
e As RunWorkerCompletedEventArgs)
'This won't work.
If MyQueue.Count > 0 Then
BGW.RunWorkerAsync(MyQueue.Dequeue)
End If
End Sub
做这些事情的正确方法是什么?初始化计时器确实浮现在脑海中,但它似乎并不正确。 (我应该给它多少时间?我应该循环到BGW 线程的结尾吗?)
或者我应该考虑其他方法而不是调用 BGW?
【问题讨论】:
-
与其尝试计算 BGW 何时完成以便重新开始,为什么不让它完成呢?为此,您需要将
DoWork事件处理程序的内容放在Do或While循环中,并且仅在队列为空时退出该循环。 FSW 在循环结束和IsBusy属性被设置回False之间添加到队列的可能性很小。不过这是一个很小的机会,无论如何,该项目将在下次处理。如果你真的很热衷,你也可以使用一些线程同步来完全阻止它。 -
@jmcilhinney,这是我最初的尝试,我放弃了正是因为这个微小的(是吗?)机会:距离下一个
FSW_Create事件可能还有几分钟,但客户端通知延迟超过几秒钟是不能容忍的。您会采用哪种同步技术?我认为在我的情况下我不能使用AutoResetEvent,正如 Tanveer Badar 下面所建议的那样,请参阅那里的评论。 -
非常无法预测您可以在什么时候对收到通知的文件执行某些操作。几乎永远不会在您收到通知的确切时间,因为该文件仍在被进程修改。当它关闭文件是不可知的。您需要一个带有线程安全队列的生产者/消费者场景,您可以在其中填充字符串。消费者可以是定期尝试清空队列的 BGW。因此,计时器是正确的方法。
-
@HansPassant,我会采用这种方法,谢谢。我如何确定该文件是否可访问?尝试在 Try-Catch 块中打开它是唯一(浪费)的可能性吗?
-
你已经知道该怎么做了。没有 File.IsLocked() 方法,它不是原子的。浪费在对文件系统执行任何操作的代码中不是问题,这样的代码总是以毫秒的速度运行。
标签: vb.net multithreading asynchronous backgroundworker filesystemwatcher