2009-05-28 8 views
7

.NET 라이브러리에서 사용할 수있는 특수 데이터 구조를 작성 중이며이 데이터 구조의 기능 중 하나는 하나의 스레드 만 데이터를 쓰고 하나의 스레드 만 읽으면 스레드 안전성이 있다는 것입니다. 그것으로부터의 데이터 (독자 쓰레드와 라이터 쓰레드는 다를 수있다)..NET에서 크로스 스레드 액세스를 검색하는 방법 (스레드 유사성 적용)?

질문은 모든 읽기 작업이 동일한 스레드에 의해 실행되도록하는 방법은 무엇입니까?

내 솔루션은 System.Threading.Thread.ManagedThreadID를 캡처하여 첫 번째 읽기시 개인 멤버에 저장합니다. 그런 다음 후속 읽기에서 ManagedThreadID를 저장된 것과 비교하여 검사하고 다른 경우 예외를 throw합니다.

그걸로 충분합니까, 아니면 이렇게하기위한 다른 신뢰할 수있는 메커니즘이 있습니다.

참고 :이 라이브러리는 Windows.Forms 컨텍스트없이 사용할 수 요구 사항이 있습니다 ..

답변

6

이 상황에 직면했을 때 나는 ThreadAffinity라는 클래스를 사용합니다. 전체 스레드의 목적은 현재 스레드를 기록하고 다른 스레드에서 잘못된 액세스를 throw하는 것입니다. 수작업으로 수표를 발행해야하지만 소량의 작업이 캡슐화됩니다. 주제에

class Foo { 
    ThreadAffinity affinity = new ThreadAffinity(); 

    public string SomeProperty { 
    get { affinity.Check(); return "Somevalue"; } 
    } 
} 

클래스

[Immutable] 
public sealed class ThreadAffinity 
{ 
    private readonly int m_threadId; 

    public ThreadAffinity() 
    { 
     m_threadId = Thread.CurrentThread.ManagedThreadId; 
    } 

    public void Check() 
    { 
     if (Thread.CurrentThread.ManagedThreadId != m_threadId) 
     { 
      var msg = String.Format(
       "Call to class with affinity to thread {0} detected from thread {1}.", 
       m_threadId, 
       Thread.CurrentThread.ManagedThreadId); 
      throw new InvalidOperationException(msg); 
     } 
    } 
} 

블로그 게시물 :

+0

감사합니다. 그냥 궁금 해서요, 어떤 이유가 보입니까 @ sixlettervariables의 답이 좋을까요/나빠질까요? –

+1

@Miky D, 나는 책임이 섞여 있기 때문에 그것이 더 나쁘다는 유일한 이유가있다. 잘못된 크로스 스레드 액세스를 확인하기 위해 별도의 클래스를 사용하면 일관성있는 재사용 환경을 제공합니다. 그것은 매우 적은 양의 코드이지만 오류 메시지는 정말 망칠 수 있습니다. 따라서 IMHO는 그리 큰 문제가 아닙니다. – JaredPar

+0

JaredPar에 관해서는 클래스를 사용하는 것에 동의하며 Managed ID를 사용하는 것에는 동의하지 않습니다. 하지만 네, +1 논리를 처리하는 다른 클래스를 사용합니다. – user7116

1

당신이 읽기를 필요로하고 방법을 쓸 수 없습니다 스레드 또는 스레드 ID를 가지고? 그런 다음 먼저 호출 한 것과 비교할 수 있습니다. 일치하지 않으면 예외를 throw하거나 오류 코드를 반환하거나 요청을 무시하십시오.

그렇지 않으면 제안한 내용도 효과가 있습니다. 스레드 ID 만 비교하면됩니다.

+0

내가 읽기/쓰기 방법의 어떤 발신자에 의존하고 싶지 않아요 입력으로 제공 .. 그렇지 않으면, 내가 안정적으로 ManagedThreadID 메서드를 사용할 수 있다면 나는 그것을 사용할 것입니다. 감사. –

1

스레드 ID를 비교하는 대신 구성 중에 클래스에 ambient Thread을 저장해야합니다.

class SingleThreadedClass 
{ 
    private Thread ownerThread; 

    public SingleThreadedClass() 
    { 
     this.ownerThread = Thread.CurrentThread; 
    } 

    public void Read(...) 
    { 
     if (Thread.CurrentThread != this.ownerThread) 
      throw new InvalidOperationException(); 
    } 

    public void TakeOwnership() 
    { 
     this.ownerThread = Thread.CurrentThread; 
    } 
} 
+0

스레드 ID와 반대되는 스레드에 대한 참조를 사용해야하는 특별한 이유가 있습니까? 귀하의 기술은 ID와는 달리 스레드에 대한 참조를 사용한다는 점을 제외하고는 매우 유사합니다. 그냥 궁금 해서요. –

+0

관리되는 스레드 ID가 재활용되는 상황이 걱정됩니다. 또한 관리 ID보다 스레드로 더 많은 작업을 수행 할 수 있습니다. – user7116

관련 문제