C#을

2017-02-27 2 views
2

소개C#을

내가 작업자 스레드에서 호출 할 추상적 인 방법으로, 공개 추상 클래스가 있습니다.

이 메서드를 호출하면 계산 중 상태가 변경되지 않도록 각 인스턴스를 잠글 수 있습니다.

상속인의 구현이 제 3 자에 의해 수행되기 때문에 나는 오직 추상 클래스로 작업하기를 원합니다.

public abstract class MyClass 
{ 
    public abstract MyResult GetData(); 
} 

내 라이브러리가 타사에서 사용하는 문제는, 나는 그들이 도서관의 내부 구현에 대해 아무것도 알고 있다고 가정합니다.

나는이 나쁜 형식을 고려할 때 자신의 상속자를 구현할 수 있기 전에 내 수업의 문서를 연구하도록 강요하고 싶지 않습니다.

내 접근

내 첫번째 생각은 클래스에 보호 잠금 개체를 추가하고 메서드를 호출 할 때 그것을 잠글 수 있었다.

그러나이 기능을 유용하게 사용하려면 제 3자가이를 고정시켜야합니다.

제 3 자에게 내부 정보를 알리고 싶지 않기 때문에이 옵션이 마음에 들지 않습니다.

public abstract class MyClass 
{ 
    protected readonly object myLock = new object(); 

    public MyResult GetData() 
    { 
     MyResult result; 

     lock(myLock) 
     { 
      result = GetDataInternal(); 
     } 

     return result; 
    } 

    protected abstract MyResult GetDataInternal(); 
} 

배경

내가 별도의 스레드에서 실행되는 데이터 파이프 라인에서 일하고 있어요.

이 파이프 라인은 데이터를 특정 형식으로 요청하고 백그라운드에서 처리합니다.

데이터를 제공하는 데 시간이 오래 걸릴 수 있으며 제공된 데이터는 개체의 속성에 의존합니다.

이 경우 3D 모델 용 준비 파이프 라인입니다.

질문 나는 그것의 구현을 모른 채 전체 개체를 잠글 수있는 방법

?

그런 방법이 없다면 합의 된 패턴이 있습니까?

+3

그냥 의견. 유형을 상속받은 사람들이 문서를 읽고 명시한 규칙을 따르도록하는 것은 나쁜 형식이 아니므로 ** 절대적으로 필요합니다 **. 그들이 성공의 구덩이에 쉽게 빠져들도록해야하지만, 당신이 당신의 타입으로부터 상속 받도록하려는 경우에는 절대 안전한 타입을 만들 수 없습니다. 아는 사람들은 예상했던 것보다 부정적인 것을 반환하는 메소드를 구현할 수 있습니다.이 스 패인 턴트 유형을 사용하는 코드의 작업에 큰 스패너를 던지십시오. –

+0

"코드를 잠그는"일반화 된 잠금이 없으며 해당 코드없이 잠금이 실행됩니다. 즉, 일부 코드가 잠금없이 객체에 액세스하고 일부 코드가 함께 사용되면 잠금을 변경하지 않고 마술처럼 첫 번째 코드를 신경 쓸 수 없습니다. 개체의 스냅 샷 만 제공하는 등의 스레드 안전 액세스를 제공하기 위해 개체를 닫을 수 있지만이 경우에도 해당 유형을 사용하는 타사 코드를 변경해야합니다. –

+0

맞습니다. 문서를 읽는 것이 필수입니다. 그러나 여기에서는 대부분의 사람들이 myLock 속성을 인식하지 못하는 직관적 인 요구 사항을 싫어합니다. 나는 (대부분의 경우) 문서가 읽힐 때만 제대로 사용되는 구현을 싫어한다. – Chillersanim

답변

1

제 도서관에서 사용하는 제 3 자 라이브러리는 라이브러리의 내부 구현에 대해 아무 것도 모르고 있다고 가정해야합니다. (..) 메서드가 호출되면 계산 중에 상태가 변경되지 않도록 각 인스턴스를 잠글 수 있습니다.

나는 최선의 방법은 ..라고 생각합니다.그들이 그것을 알게하고 그들이 책임을지고 있음을 확인하십시오. (많은) 문서없이 쉽게 직관적으로 만들 수 있습니다.

public interface ILockable 
{ 
    void FreezeDataForCalculations(); 
    void ThawAfterCalculations(); 
} 

public abstract class MyBaseClass<T> where T:ILockable 
{ 
    public abstract T GetData(); 
} 

사용법 : 지금, 당신은 효과적으로 것을 보장

public class MyThingie : MyBaseClass<TheActualData> 
{ 
} 

public class TheActualData : ILockable 
{ 
    public string Foo {get;set;} 

    public void FreezeDataForCalculations() { ...???...} 
    public void ThawAfterCalculations() { ....???.... } 
} 

: 원하는 누구든지

  • 그것을 구현하는가에있다

    처럼 뭔가에 추상 클래스를 변경하는 것이 좋습니다 직접 인터페이스를 구현하는 자체 유형 제공
  • 누구든지 별도의 인터페이스 이 두 가지 방법을 알 수 있습니다, 그들은 적어도 생각한다 "태권도 연맹"것이며, ​​immediatelly 이해하거나, 문서를
  • 하면 데이터에 대한 잠금을하지 않는다, 창조 컨설팅 시도 할 것이라는 점을 implementa 이
  • 구현 지금 실제로 동결/해동 쌍을 구현하는 whever를 선택하거나 비워두고 단순히
  • 코드가 지금 가지고있는 그 사이에 데이터를 수정하지 않는 자신의 코드를 작성하기위한 클래스의 책임 'Freeze'와 'Thaw'를 적절하게 호출하고, 구현자가 예상 한 바를 수행했다고 가정 할 수있다.

반대로 사용자가 예상했던대로 수행 할 수 없다고 가정하면 라이브러리의 API를 변경하고 사용자 정의 유형을 허용하지 않고 API를 자신의 유형으로 만 제한하십시오 당신은 좋은 플레이를 보장 할 수 있습니다.

+0

이것은 아름답고 단순합니다. 누군가가 이것을 무시하면 분명히 자신의 잘못입니다. 나에게 좋은 해결책 인 것 같아. 고맙습니다! – Chillersanim

+0

나는 이것이 원래의 디자인에서 한 걸음 뒤로 물러 났다고 생각한다. 문제는 잠금 동작을 숨기는 방법에 관한 것입니다. OP의 코드가 바로 그랬습니다. 이것은 자물쇠의 필요성을 드러내고 소비자에게 책임을 묻는 반대의 역할을합니다. 원본을 개선 할 수있는 방법이있을 수 있지만 의도를 성취하는 것입니다. 클래스를 상속받은 누군가는 필요한 기능을 채울 수 있지만 잠금이 진행되고 있음을 알 필요조차 없습니다. –

+0

그것을 보는 또 다른 방법 - 누군가가 클래스가하는 것과 명백한 관계가없는 메소드를 호출해야합니다. 모든 클래스, 심지어 문자열은 다양한 스레드의 상태 변화로부터 보호해야 할 수도 있습니다. 잠글 필요가있는 클래스를 명시 적으로 "표시"하는 패턴을 만드는 것은 바람직하지 않습니다. 다른 모든 것이 암시 적으로 스레드로부터 안전하다는 것을 의미합니다. –

관련 문제