2017-01-25 5 views
0

同じTCPポートに接続する2つのasync-awaitがあります。2つの異なるスレッドのミューテックスまたはセマフォ

RSPすべて20000msです。

SPすべて500msです。

別のメソッドRPは、呼び出されるたびにポーリングするため、ランダムにすることができます。

今のところ、RPが数回呼び出されると、システム全体がフリーズします。

セマフォまたはミューテックス、この場合、より適しているであろう場合、私は知りたいのですが、私はそれをどのように使用する必要があります。

私はセマフォの例をチェックしましたが、ほとんどの方法が1つの方法を使用していますが、同時に5つを実行しようとしているようです。 2つの異なる方法でどのように使用できますか?

static SemaphoreSlim _sem = new SemaphoreSlim(1, 1); 
public async void RSP() 
{ 
    await Task.Run(() => 
    { 
     while (true) 
     { 
      _sem.Wait(); 
      //DoWork 
      _sem.Release(); 
      Thread.Sleep(20000); 
     } 
    } 
    ); 
} 

public async void SP(CancellationToken token) 
{ 
    await Task.Run(() => 
    { 
     while (true) 
     {     
      try 
      { 
       if (token.IsCancellationRequested) 
       { 
        return; 
       }   
       _sem.Wait(); 
       //DoWork 
       _sem.Release(); 
      } 
      catch (Exception) 
      { 
       if (token.IsCancellationRequested) 
       { 
        return; 
       } 
       break; 
      } 
      Thread.Sleep(500); 
     } 
    }); 
} 

答えて

0

あなたは(静かに)あなたのcatchハンドラでExceptionを無視すると、悪いことが起こります。

try 
{ 
    //... 
    _sem.Wait(); 
    //if an exception happens here 
    //you won't know about it because 
    //logic in the catch means it will 
    //be ignored. 
    //Even worse... the line below won't be called 
    _sem.Release(); 
} 
catch (Exception) 
{ 
    //... 
    break; //oh s**t. how will we ever know? 
} 

デッドロックのための完全なレシピです。

改善する方法あなたは、同期ブロッキング操作をたくさんやってasync awaitとそれらを混合しているよう余談として

try 
{ 
    //... 
    _sem.Wait(); 
    try 
    { 
     //do work 
    } 
    finally 
    { 
     _sem.Release(); //called, even if there's an exception 
    } 
} 
catch (Exception) 
{ 
    //... 
    //this is just sloppy. never ignore ALL exceptions 
    //fix this. 
    break; 
} 

は、それが見えます。これはそれがどのように使用されるのかではありません。あなたが使用していないように見える仕事/非同期のネットワーク方法があります。await Task.Delayを使用できるThread.Sleepを使用しています。 SemaphoreSlimは、WaitAsyncメソッドを使用してセマフォを待機するためのタスク/非同期サポートを提供します。おそらくあなたのコードには、待機、スリープ、または同期IOで実行を停止する必要があります。非同期を適切に学習し、待機中またはスリープ状態にあるスレッドでThreadPoolを止めます。

関連する問題