在Windows窗体中,我有:


定期执行本地数据库备份的计时器tmrBackup
当FileSystemWatcher在给定目录中检测到新文件时,引发事件过程ImportNewFile的事件过程。


只要它们不会互相干扰,它们中的每一个都可以完美地工作。

我试图通过在备份开始时停止FileSystemWatcher并在备份完成后再次启动来防止这种情况。

另一方面,我在ImportNewFile的开头设置了tmrBackup.Stop(),然后将文件的内容转换为本地数据库中的记录。在ImportNewFile的末尾,我再次设置tmrBackup.Start()。但是计时器永远不会再启动,因此这似乎不是可行的方法。

但是,当我未设置tmrBackup.Stop()时,我会在调试过程中看到一个奇怪的行为:当ImportNewFile中的某个位置触发计时器时,似乎两个例程都在并行运行:执行tmrBackup例程中的一行,然后执行VB .Net跳回到ImportNewFile一行,然后回到计时器,依此类推。

问题:处理两个对象且每个对象能够在处理另一个事件时触发的正确方法是什么?谢谢!

最佳答案

在这种情况下,典型的解决方案不是在临时禁用相反的定时器(这是很关键的并且不能保证能正常工作),而是在每个事件处理程序中的必要代码周围放置SyncLock块,并使它们都与同一对象。

当代码被SyncLock包围时,执行将停止并等待,直到进入SyncLock块,直到其他任何相关的SyncLock代码完成为止。关联它们的方法是通过给SyncLock语句一个同步对象。如果两个SyncLock块同步到同一对象,则将不允许这两个代码块同时运行。

换句话说,如果两个代码块同时被调用,则以第一个开始的那个为准,然后一直运行直到完成为止,第二个代码块等待开始执行,直到第一个完成为止。

Public Class SyncLockExample
    Private WithEvents object1 As MyType1
    Private WithEvents object2 As MyType2
    Private syncObj As New Object()

    Private Sub object1_MyEvent1(Object sender, EventArgs e) Handles object1.MyEvent1
        SyncLock syncObject
            ' Do something that can't happen at the same time as object2_MyEvent2
        End SyncLock
    End Sub

    Private Sub object2_MyEvent2(Object sender, EventArgs e) Handles object2.MyEvent2
        SyncLock syncObject
            ' Do something that can't happen at the same time as object1_MyEvent1
        End SyncLock
    End Sub
End Class

10-08 17:04