2016-10-24 6 views
-1

たとえば、ファイルがフォルダに追加されるたびにイベント通知が発生します(これは私の場合ではなく、の説明に過ぎません)。注文のプロセスタスク

フォルダに追加されるファイルの数はいくつでもかまいませんが、そこにいくつのファイルがあるかはわかりません。

は現在、私のイベントmyEvent_Handlerファイルが上記のイベントハンドラで問題がところででマークされた行の競合状態である

private void myEvent_Handler(object sender, SomeEvent e) 
{ 
    // I dont know how many times this event will fire 
    if (something == true) (1) 
    { 
    var t = Task.Run(() => 
    { 
     DoSomething(e); (2) 
    }); 
    } 
} 

が追加されるたびに発射(1)及び(2)。例えば、イベントは、4回焼成される。

  1. 、(2)実行するタスクにキューイングされている(1)が真である
  2. (1)、(2)にタスクに真のキューイングされています実行
  3. 、(2)を実行するタスクにキューイングされた(1)真である
  4. 、(2)タスクキューがあり、今

を実行するタスクにキューイングされた(1)真であります実行するタスクは4つですが、これらは同じ順序で実行されません。 3> 2-> 4-> 1の順番で実行できますが、UIスレッドをブロックせずに1-> 2-> 3-> 4のように実行する必要があります。

UIスレッドをブロックせずにこれを実現するにはどうすればよいですか?

+2

タスクのキューのような音 – stuartd

+3

は、キューで長い実行中のタスクを使用できるように聞こえます。解決策を見てください:http://stackoverflow.com/questions/2293976/how-and-if-to-write-a-single-consumer-queue-using-the-tpl – muratgu

+2

[Queue](https:// msdn.microsoft.com/en-us/library/system.collections.queue(v=vs.110).aspx)または多分[スレッドセーフキュー](http://stackoverflow.com/questions/13416889/thread-safe -queue-enqueue-dequeue)? –

答えて

-2

私はそれを考え出したと、これを行うために上記の私のコードを書き直しました:

private void myEvent_Handler(object sender, SomeEvent e) 
{ 
    // I dont know how many times this event will fire 
    Task t = new Task(() => 
    { 
    if (something == true) 
    { 
     DoSomething(e); 
    } 
    }); 
    t.RunSynchronously(); 
} 

素晴らしい働いていると私のUIスレッドをブロックしていないこと。

UPDATE:私の競合状態が改善され、UIスレッドがブロックされていないことがわかりましたが、さらに調査すると、このコードを呼び出すメソッドがUIスレッドで実行されていないことがわかりました(なぜこのコードは私のUIスレッドをブロックしていないのか説明していますがManagedThreadIdをチェックしています)、上記のタスクはこのメソッドが実行されている同じスレッドで実行されていました。 その結果、私はこれらの2件の記事によると、私の実装を変更:

https://msdn.microsoft.com/library/system.threading.tasks.taskscheduler.aspx

How (and if) to write a single-consumer queue using the TPL?

をソリューションがうまく機能することをMSDNの記事の上で提供さLimitedConcurrencyLevelTask​​Scheduler(

を使用するために、タスクを。パフォーマンスを向上させるインスタンス化されたタスクのメソッドと同じスレッドで実行されていません。

+0

[タスクコンストラクタはほとんど使用しないでください。この例も例外ではありません。](http://blog.stephencleary.com/2014/05/a-tour-of-task-part-1-constructors.html)。 –

+0

@ErikPhilipsを詳しく説明してもらえますか? – pixel

+0

ブログにリンクしていると書いている内容を書き直すとは思いません。 –

0

Microsoftのリアクティブフレームワーク(NuGet "System.Reactive")を使用してこれを行います。それは理想的です。

Observable 
    .FromEventPattern<EventHandler, EventArgs>(
     h => myEvent.Handler += h, h => myEvent.Handler -= h) 
    .ObserveOn(Scheduler.Default) 
    .Subscribe(ep => DoSomething(ep.EventArgs)); 

これは、バックグラウンドスレッドを自動的にマーシャリング(Scheduler.Default)し、それが前の1がオンに移動する前に完了するまで、各サブスクリプション・コールが待機していることを保証します。

これは、myEvent_Handlerメソッドを完全に置き換えることができます。

.Subscribe(...)コールではIDisposeが返され、いつでも処理を停止することができます。これは事実上イベントから切り離されます。