使用FileSystemWatcher共享同一个事件处理程序是否安全?

5
使用FileSystemWatchers共享同一个事件处理程序是否安全?使用具有不同目录的多个FileSystemWatchers使用相同的事件处理程序是否安全?
Class Snippets
    Private _watchPaths As New List(Of String) From {"x:\Dir1", "x:\Dir2"}
    Private _watchers As List(Of FileSystemWatcher)
    Private _newFiles As New BlockingCollection(Of String)

    Sub Watch()
        Dim _watchPaths As New List(Of String) From {"x:\Dir1", "x:\Dir2"}
        Dim watchers As List(Of FileSystemWatcher)

        For Each path In _watchPaths
            Dim watcher As New FileSystemWatcher
            AddHandler watcher.Created, Sub(s, e)
            _trace.DebugFormat("New file {0}", e.FullPath)
            'Do a little more stuff
            _newFiles.Add(e.FullPath)
            End Sub
        Next
    End Sub
End Class

我们需要将FileSystemWatcher包装在以下类中,以使事件处理程序线程安全吗?
Class FileWatcher
    Private _fileSystemWatcher As New FileSystemWatcher

    Public Sub Start(path As String, filter As String, action As Action(Of Object, FileSystemEventArgs))
        With _fileSystemWatcher
            .Path = path
            .Filter = filter
            .EnableRaisingEvents = True
            AddHandler .Created, Sub(s, e)
            action(s, e)
            End Sub
        End With
    End Sub

    Public Sub [Stop]()
        _fileSystemWatcher.Dispose()
    End Sub
End Class

这里是助手类的使用方法:

Sub Watch
    For Each path In _watchPaths
        Dim Watcher as new FileWatcher
        watcher.Start(path, "*.txt"), Sub(s, e)
        _trace.DebugFormat("New file {0}", e.FullPath)
        'Do a little more stuff
        _newFiles.Add(e.FullPath)
        End Sub)      
    Next
End Sub
1个回答

3
FileSystemWatcher引发的事件默认在线程池线程上引发。这意味着无论您是否有多个处理程序,事件处理程序中使用的任何数据都是“共享”的。为避免损坏,应该保护(例如lock访问)此共享数据。

或者,您可以使用FileSystemWatcher.SynchronizingObject提供同步上下文,以便在单个或已知线程上发生FileSystemWatcher引发的所有事件。如果事件处理程序触摸GUI元素,则通常执行此操作。


我扩展了代码样例,以展示帮助类FileWatcher的用法。这种方式事件处理程序是线程安全的吗? - Peter Meinl
如果唯一的“共享”数据是 BlockingCollection 对象,则您是线程安全的。 如果您添加了其他内容,则必须使用类似于 SyncLock 的东西。 - Peter Ritchie
好的,那么我使用共享FileSystemWatcher事件的第一个示例是不安全的。但是,像FileWatcher示例中所做的那样将FileSystemWatcher封装在类中应该是线程安全的,而无需任何锁定,因为每个Created()事件处理程序都在其自己的FileSWatcher实例中运行。或者我错过了什么? - Peter Meinl
我认为按照上述方法将FSW封装在一个类中可以使事件处理程序线程安全。 - Peter Meinl
@PeterMeini,你编写事件处理程序,所以不,这并不使它们“线程安全”。这只意味着它们在您为“SynchronizingObject”提供的任何同步上下文中被调用。由于这是一个WinForms控件,这意味着所有对事件处理程序的调用都在单个UI线程上执行。但是,这并不能使您的事件处理程序自动成为线程安全的。 - Peter Ritchie
Peter Ritchie,感谢您回复。我以为通过在单独的FileWatcher帮助类实例中创建每个FSW,可以防止不同线程同时调用FSW事件处理程序。这个假设真的是错误的吗?顺便说一下,没有UI线程,我正在Windows服务中使用FSWs。 - Peter Meinl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接