まず背景として、 Duplicitiy (github.com で)という名前のオープン ソース .NET ライブラリを作成しました。これは を使用して、 FileSystemWatcher
2 つのディレクトリ間ですべてのファイル変更を複製します。
実装するFileSystemObservable
クラスを作成しました( FSWatcherIObservable<FileSystemChange>
を使用して実際のをラップします)。ファイルまたはディレクトリが作成、変更、または削除されると、Reactive Extensions を使用して変更が公開されます。FileSystemWatcher
Subject<FileSystemChange>
次に、次のサブスクリプションを使用して、このオブザーバブルをサブスクライブします。
return observable
.Buffer(() => observable.Throttle(TimeSpan.FromSeconds(2)).Timeout(TimeSpan.FromMinutes(1)))
.PrioritizeFileSystemChanges()
.SelectMany(x => x);
変更は、最大 1 分間、変更がない状態が少なくとも 2 秒間続くまでバッファリングされます。これは、ディレクトリを削除するときに、FileSystemWatcher
が含まれているすべてのファイルとディレクトリについて通知するためです。ディレクトリ内に含まれる変更を飲み込み、サブスクライバーの親を削除するだけで、動作を最適化できます。これはPrioritizeFileSystemChanges
フィルターによって処理されます。また、バッファ ウィンドウ内で作成され、その後削除されたファイルを無視することもできるため、ターゲットでの IO 操作が再び減少します。
これは、失敗/再試行をサポートしていない現時点では単純な方法ではありますが、機能します。
ただし、私の質問は、このオブザーバブルのサブスクライバーが各変更を処理するのにかなりの時間がかかる可能性があるということです。たとえば、大きなファイルを低速のファイル システムにコピーします。現在コピーされている同じファイルに対して新しいファイル システムの変更が発生した場合、進行中の操作を中止するにはどうすればよいですか。または、ファイルがバッファリングされたリストに含まれているが未処理の場合、どのように削除または除外できますか?
元のオブザーバブルへの別のサブスクリプションが必要になると思いますが、状態を共有したり、保留中のタスクを変更したりするのに最適な方法がわかりませんか? 変更は、受信した順序で処理する必要があります。これはキューを示します。ただし、新しいファイル システムの変更は、キャンセルまたは削除する必要があるキュー操作に適用される場合があります。キューは、順不同の削除用に設計されていません。
たとえば、現在ファイルFoo\Bar.txt
をコピーしていて、Foo
ディレクトリが削除されているとします。次に、ディレクトリおよびすべてのサブディレクトリに対する進行中または保留中の変更をキャンセルする必要があります。これは Task Parallel Library の使用例でしょうか、それとも私が取れるリアクティブなアプローチはありますか?
github のプル リクエストもお待ちしております。