2015-08-31 128 views

回答

1

一般來說,沒有保證。

事件處理程序在它所調用的同一個線程上運行,但並不真正告訴你任何事情 - 對於你所知道的,它可以用ThreadPool.QueueUserWorkItem(() => EventHandler())之類的東西調用。 System.Timers.Timer就是一個例子 - 定時器回調在線程池線程上調用,並且多個可以並行運行。

主要的例外情況是某些同步上下文使用的事件 - 例如,Windows窗體中的GUI事件(包括System.Windows.Forms.Timer)只會在GUI線程上啓動。但是,文檔應明確指定事件處理程序具有某種特定的線程關聯 - 它當然不是默認假設。

FileSystemWatcher特別是更棘手。如果它有一個SynchronizingObject集合,它將具有線程關聯 - 將在同步對象上調用處理程序。例如,如果該同步對象是Form,則處理程序將始終在GUI線程上運行,並且永遠不會並行運行。其他同步對象的行爲可能會有所不同(例如,您始終可以創建自己的同步對象,將代理髮布到線程池)。請注意,調用是異步的 - 它確實是BeginInvoke,而不是Invoke - 所以如果您的同步對象執行類似ThreadPool.QueueUserWorkItem的操作,它可能會導致並行執行。

如果沒有同步對象,則處理程序在接收通知的同一個線程上運行。由於FileSystemWatcher在IOCP上運行,假設它只是在回調期間借用一個線程池線程是非常安全的。 但是,它也顯式地在整個代碼周圍,包括事件處理程序調用 - 所以它不會並行運行。

0

addremoveFileSystemWatcher類的處理程序沒有什麼特別的 - 因爲在大多數情況下 - 它是完全無關緊要的,從哪個線程訂閱一個方法。如果您設置了FileSystemWatcher.SynchronizingObject,則將通過BeginInvoke調用在該對象上調用委託;否則, 它將在您的FileSystemWatcher所在的地方調用。

委託的方法將在調用者的線程中相互調用,因此它們之間沒有同步問題。但是,如果在其他線程中使用了訂閱方法的公共資源,則必須像往常一樣照顧同步。