2016-07-05 10 views
-1

私はFileSystemWatcherを登録し、いくつかのメソッドを実行する次のコードを持っていますDoRequiedWork()指定されたファイルに対して書き込みイベントが発生するたびに。私は、パフォーマンスを改善するための試みでc++ API ReadDirectoryChangesWを使ってこれを実装したいと思いますFileSystemWatcherのパフォーマンスを向上させる

// To prevent multiple events from firing 
static DateTime lastRead = DateTime.MinValue; 
static string UserName = GetUserName(); 

private static void Run() 
{ 
    // Create a new FileSystemWatcher and set its properties. 
    var watcher = new FileSystemWatcher 
    { 
     Path = [email protected]"\\file\home$\{UserName}\Application Data", 
     NotifyFilter = 
      NotifyFilters.LastWrite, 
     Filter = "filetowatch.txt" 
    }; 

    // Activate 
    watcher.Changed += OnChanged; 
    watcher.EnableRaisingEvents = true; 

    while (true) 
    { 
     System.Threading.Thread.Sleep(10000); 
    } 
} 

private static void OnChanged(object source, FileSystemEventArgs e) 
{ 
    var lastWriteTime = File.GetLastWriteTime(e.FullPath); 

    if (lastWriteTime == lastRead) return; 

    DoRequiredWork(); 

    lastRead = lastWriteTime; 
} 

、しかし:あり(lastReadlastWriteTimeで)各書き込みに発射から複数のイベントを防ぐために、そこにいくつかのロジックもありますこれを行う方法がわかりません。

私はpinvokeを確認し、署名のように定義することができることを見ることができます:私はこれを作成する方法を見て開始したいが、最初、これは実際に実行するかどうかをチェックしたいでしょう

[DllImport("kernel32.dll")] 
static extern bool ReadDirectoryChangesW(IntPtr hDirectory, IntPtr lpBuffer, 
    uint nBufferLength, bool bWatchSubtree, uint dwNotifyFilter, out uint 
    lpBytesReturned, IntPtr lpOverlapped, 
    ReadDirectoryChangesDelegate lpCompletionRoutine); 

標準よりも優れており、管理されているC#FileSystemWatcherです。私は感覚を得るのよう

while (true) 
{ 
    System.Threading.Thread.Sleep(10000); 
} 

代わりに(またはそれに加えて)、私は(UIなしで)バックグラウンドで実行中のアプリケーションを維持するより良い方法がより存在しているかどうかを知りたいですこれはアプリを開いたままにする最良の方法ではないかもしれませんが、わかりません。

誰にでもアドバイスできますか?

+1

(http://referencesource.microsoft.com/#System/services/io/system/io/FileSystemWatcher.cs)[ 'FileSystemWatcher'はすでに' ReadDirectoryChanges'を使用しています]ので、あなたは物事を改善する可能性は低いですあなた自身でそれをすることによって。 –

+1

.NET Core 1.0の開発中、マイクロソフトはこの分野のパフォーマンスに関する複数の問題を特定しています。 .NET Frameworkでそれらを実装するまで待つか、.NET Core 1.0 RTMアプリケーションを開発する必要があります。 –

+1

@MatthewWatsonこれはMicrosoftがこのクラスにバグを持っていれば100%真実ではありません。 –

答えて

2

Runメソッドのスレッドを保持しているようです。それをしないでください。代わりに静的な参照を保持してください。あなたはネットワーク共有を見ているようです。ディスクサブシステムだけでなく、ネットワークサブシステム(サーバーとサーバーの両方)が関与するだけでなく、高いパフォーマンスを期待しないでください。同じAPIをネイティブに呼び出すと突然大規模なパフォーマンスが得られると予想するには、あまりにも多くの要因が関係します。

static FileSystemWatcher watcher; 

private static void Run() 
{ 
    // Create a new FileSystemWatcher and set its properties. 
    // if you're watching a network share, don't expect huge performance 
    // as the network is involved 
    watcher = new FileSystemWatcher 
    { 
     Path = [email protected]"\\file\home$\{UserName}\Application Data", 
     NotifyFilter = 
      NotifyFilters.LastWrite, 
     Filter = "filetowatch.txt" 
    }; 

    // Activate 
    watcher.Changed += OnChanged; 
    watcher.EnableRaisingEvents = true; 

    AppDomain.CurrentDomain.DomainUnload += (s,e) => { 
     var w = watcher as IDisposable; 
     if (w != null) w.Dispose(); 
    }; 
} 
+0

あなたの答えはありがとうございます。私が「糸をつかんでいる」と言うとき、あなたは 'While(true){sleep} 'ループを指していますか?このFileWatcherは、必要なフォルダを常に見る必要があり、他の方法で行うことは考えられませんでした。他のオプションは 'MOF'サブスクリプションを登録していましたが、(exoyingly)exeやシェルプログラムを実行できません。ファイルの変更が検出されたときに必要なことです。 – Bassie

+1

これはどこから呼び出すのですか? – rene

+0

これはC#の実行ファイル( 'Run()'は単に 'Main()'の中で呼び出されます)にあり、イベントハンドラは2番目のexeを呼び出すことができます。 MOFおよびWQLサブスクリプションを使用してWMI FileWatcherを作成しようとすると、UIとのやり取りやシェルコマンドの呼び出しができないため、失敗しました。私がもともとMOF/WQLを好んだ理由は、これらがフォルダを監視するためにバックグラウンドで実行されているEXEを必要としないからです。なぜなら、C# 'FileSystemWatcher'は(CLARITY - DoRequiredWork()ファイルシステム) – Bassie

関連する問題