2010-11-03 92 views
2

這有點複雜,但我會盡可能地盡力解釋。等待FileSystemWatcher事件在完成線程之前觸發

我使用的FileSystemWatcher的與

toFileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.FileName; 

一個通知過濾器我有一個.Created方法和.Changed方法。

當.Created事件觸發時,它會使用觀察器提供的文件名進行一些初步檢查,檢查是否已經看到文件,獲取目標文件夾並返回驗證信息。

我遇到了一個問題,即驗證是在.Created方法的末尾,它在將文件複製到目標文件之前訪問該文件進行一些驗證。當我到達這一點時,如果文件很大並且仍然處於從源文件複製的過程中,它將返回一個io「文件已被使用」的錯誤。

我想要做的是完成所有的初步代碼,然後我希望線程「掛起」,直到該文件的.Changed方法觸發指示文件完成,因爲我只捕獲更改最後一個訪問過濾器。

回答

1

我會設置一個單獨的線程使用生產者 - 消費者模式,監視項目出現在隊列中。這些項目將代表文件更改幷包含諸如文件路徑和發生的更改類型等信息。您的事件處理程序只會將項目發佈到隊列中,並讓消費者線程出列並處理信息。這會將您需要的處理從文件系統通知事件中分離出來,從而更容易避免出現「正在使用的文件」問題。

+0

+1,表示同意。但起皺:它不是典型的生產者 - 消費者模式。操作成功後才能使用。 – 2010-11-03 21:21:47

+0

是的,絕對有一些棘手的細節需要解決...... – 2010-11-05 02:41:51

2

使用可以使用ManualResetEvent。 Created方法可以完成它的工作,然後等待Created方法可以繼續的Changed事件信號。

1

這個問題很正常,當其他進程忙於寫入文件時,通常無法打開該文件。你需要等待,你無法預測什麼時候會完成。將文件路徑添加到列表中,並使用計時器清空該列表,並定期重試該操作。小心邏輯,你使用線程,所以你需要用鎖來保護列表。

+0

我確實考慮過一個涉及計時器的模型,但我真的寧願不使用計時器或任何類型的循環。我知道他們是有效的,但我試圖將我的編程風格推向事件驅動的調用。 – Patrick 2010-11-04 12:26:54

+0

好吧,如果你足夠了解寫入文件的過程,那麼你可能不會使用FSW。 – 2010-11-04 12:39:04

+0

該過程本身需要能夠處理20-30個不同的文件,並將它們放置在所需的位置......這也不是項目特定的功能。這是現在和將來將繼續在整個公司的多個不同項目中使用的東西。 – Patrick 2010-11-04 13:15:58

1

請注意,NotifyFilters.LastAccess並不意味着您會知道何時其他進程已完成文件。它只是意味着當文件的上次訪問時間發生變化時您會收到通知。

我通常會與Brian Gideon的生產者 - 消費者模式一起去。這也可以很容易地過濾掉FileSystemWatcher愉快舉動的(典型)多個事件。

(幾乎)確定其他進程已完成文件的唯一方法是試圖獲取排它鎖。雖然這並不總是足夠的。我見過一個FTP服務器,它關閉並重新打開它寫入的每個塊的文件;-)

請注意,FileSystemWatcher確實有一個內部緩衝區,用於緩衝它從Windows獲得的文件通知,但如果很多事情發生,這個緩衝區可能會溢出。這也是創建生產者 - 消費者的原因。

我通常會通過創建一個例程來修改此問題,該例程可以手動掃描觀看的目錄,然後稍後運行一次。是的,民意調查;-)

有了這個例程也是很好的時候啓動你的應用程序。文件可能已經到達,而它已經關閉了!