2014-10-18 6 views
0

Ninject.Extensions.Interception.DynamixProxy를 사용하여 인터셉터를 작성하여 메소드 완료 시간을 기록하려고합니다. 이 같은 단일 스레드 환경 무언가에다중 스레드 환경에서 Ninject 차단

작동 : 스톱워치가 호출간에 공유되기 때문에 이것은 그러나 작동하지 않을

public class TimingInterceptor : SimpleInterceptor 
{ 
    readonly Stopwatch _stopwatch = new Stopwatch(); 
    private bool _isStarted; 


    protected override void BeforeInvoke(IInvocation invocation) 
    { 
     _stopwatch.Restart(); 
     if (_isStarted) throw new Exception("resetting stopwatch for another invocation => false results"); 
     _isStarted = true; 
     invocation.Proceed(); 
    } 

    protected override void AfterInvoke(IInvocation invocation) 
    { 
     Debug.WriteLine(_stopwatch.Elapsed); 
     _isStarted = false; 
    } 
} 

멀티 스레드 시나리오에서. BeforeInvoke에서 AfterInvoke로 StopWatch의 인스턴스를 전달하여 호출간에 공유되지 않게하는 방법은 무엇입니까?

답변

3

각 스레드가 자체 개체 그래프를 가져와야하기 때문에 멀티 스레드 응용 프로그램에서 정상적으로 작동합니다. 따라서 어떤 작업을 처리하기 시작할 때 새 그래프를 해결하고 그래프를 스레드에서 스레드로 전달해서는 안됩니다. 이를 통해 응용 프로그램에서 모든 스레드를 연결하는 단일 위치 (스레드 안전 (및 안 아는 것))에 대한 지식을 유지할 수 있습니다 (composition root).

이렇게하면이 인터셉터를 사용하여 싱글 톤 클래스를 모니터링 할 때마다 (각 스레드에서 사용됨) 각 스레드는 (일시적으로 등록 된 경우) 자체 인터셉터를 얻게된다는 것을 의미합니다. 당신은 새로운 인터셉터를 얻는다. (같은 '도청 된'인스턴스를 재사용하더라도).

그러나 이것은 차단 된 구성 요소를 주입 할 때 매우주의해야한다는 것을 의미합니다.이 도청 된 객체를 다른 단일체에 주입하면 다시 문제가 발생할 수 있습니다. 이 특별한 종류의 '문제'는 captive dependency a.k.a 라이프 스타일 불일치라고합니다. 실수로 컨테이너를 잘못 구성하여 문제가 생기기 쉽습니다. 불행히도 Ninject는 이에 대해 경고 할 수있는 가능성이 없습니다.

데코레이터를 사용하면 모든 것을 한 가지 방법으로 유지할 수 있으므로 인터셉터 대신 데코레이터를 사용하는 경우 문제가 사라질 수 있습니다. 이것은 데코레이터가 스레딩 문제를 일으키지 않고 싱글 톤이 될 수 있음을 의미합니다. 예 : 올바르게 디자인에 SOLID 원칙을 적용 할 때 자주 대규모로 장식을 적용 할 수 있도록 분명한 일반적인 추상화가 필요하기 때문에 물론

// Timing cross-cutting concern for command handlers 
public class TimingCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand> 
{ 
    private readonly ICommandHandler<TCommand> decoratee; 

    public TimingCommandHandlerDecorator(ICommandHandler<TCommand> decoratee) 
    { 
     this.decoratee = decoratee; 
    } 

    public void Handle(TCommand command) 
    { 
     var stopwatch = Stopwatch.StartNew(); 
     this.decoratee.Handle(command); 
     Debug.WriteLine(stopwatch.Elapsed); 
    } 
} 

는 장식의 사용은 종종 가능하다 시스템의 클래스 범위. 레거시 코드 기반에서 데코레이터를 효율적으로 사용하기는 어렵습니다.

관련 문제