2017-01-25 16 views
0

У меня есть два async-await, который подключается к тому же TCP-порту.Мьютекс или Семафор для двух разных потоков

RSP опросы каждый 20000ms.

SP опросы каждый 500ms.

Другой метод, RP, опросы, когда он называется, поэтому он может быть случайным.

На данный момент, когда RP называется несколько раз, вся система зависает.

Я хотел бы знать, если Семафор или мьютекс будет более подходящим в этом случае и как я должен использовать его.

Я проверил примеры для Семафор, но похоже, что большинство из них использует один метод, но одновременно пытается запустить 5 из них. Как я могу использовать их по двум различным методам?

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

Когда вы (молча) игнорировать Exception в вашем catch обработчика, плохие вещи случаются.

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? 
} 

Это идеальный рецепт для мертвого замка.

Как улучшить?

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; 
} 

Как и в сторону, похоже, что вы делаете много синхронных операций блокирующих и смешивая их с async await. Это не значит, что он предназначен для использования. Существуют сетевые методы Task/async, которые, похоже, вы не используете, вы используете Thread.Sleep, где вы можете использовать await Task.Delay. SemaphoreSlim предлагает поддержку Task/async для ожидания семафора с помощью метода WaitAsync. Вероятно, в вашем коде нет ничего, что требует остановки выполнения с ожиданием, сном или синхронизацией ввода-вывода. Изучите правильную асинхронность и прекратите связывать ThreadPool с потоками, которые сидят вокруг ожидания или сна.