2016-06-30 4 views
9

У меня есть обратный вызов MockHttpListener, используемый в модульном тестировании. Я добавил замок к нему, как показано ниже:Деградация производительности при использовании блокировки внутри try

public void HandleRequest(HttpListenerContext context) 
{ 
    try 
    { 
     lock (m_guard) 
     { 
      do something short; 
     } 

     do the actual handling (longer) 
    } 
    catch (HttpListenerException e) 
    { 
     ... 
    } 
    catch (Exception e) 
    { 
     ... 
    } 
    ... 
} 

я столкнулся с проблемой, когда тест не из-за «слишком долго» критерии мы имеем (я не сталкивался с этой проблемой в тесте перед добавлением . замок)

Я пытался много вещей, чтобы определить проблему и единственным, которое фиксировало вопрос принимает блокировку вне Ьги блока:

public void HandleRequest(HttpListenerContext context) 
{ 
    lock (m_guard) 
    { 
     do something short; 
    } 
    try 
    { 
     do the actual handling (longer) 
    } 
    catch (HttpListenerException e) 
    { 
     ... 
    } 
    catch (Exception e) 
    { 
     ... 
    } 
    ... 
} 

изменения поведения является последовательным в отношении, что местоположение блокировки относительно блока try повлияло на durat Ион прошел тест.

У кого-нибудь есть идеи по поводу причины?

+2

считают чтение этого http://stackoverflow.com/questions/5997360/locking-a-resource-via-lock-within-try-is-it-wrong. Это даст вам представление, почему это происходит. – hazevich

+0

@hazevich Это не говорит вам * почему * это медленнее, но это говорит вам, что * вы никогда не должны позволять необработанному исключению выйти из блока блокировки. Вам нужно использовать 'try/finally' INSIDE блок' lock' для очистки вещей. Но это не помогает ОП здесь, говорит. –

+0

Я прочитал нить в ссылке, но в ней обсуждается правильность использования блокировки в блоке try. Меня интересует только влияние производительности. блокировка блокировки для всех рассмотрений может считаться состоящей только из: m_some_member ++; и ничто другое, поэтому оно вполне безопасно само по себе. – shlomi

ответ

0

Похоже, что это может быть тупик - делает ли код «делать что-то короткое» в любой код, который сам берет блокировку?

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

class Program 
{ 
    static void Main(string[] args) 
    { 
     Locks.DoStuff(Enumerable.Range(0, 10000).Select(e => 9999 - e).ToList()); 
    } 
} 

static class Locks 
{ 
    public static void DoStuff(List<int> blah) 
    { 
     try 
     { 
      lock (blah) 
      { 
       for (var i = 0; i < blah.Count; i++) 
       { 
        blah[i] = 1000/blah[i]; 
       } 
      } 
     } 
     catch (DivideByZeroException e) 
     { 
      Trace.WriteLine("Exception - divided by zero"); 
     } 
    } 
} 
Смежные вопросы