2011-10-06 4 views
1

사용자 클래스에서 발생하는 이벤트를 통해 GUI 요소를 업데이트하면서이 문제가 발생했지만 다음과 같이 처리 할 수있었습니다 :다른 스레드가 스레드를 소유하고 있기 때문에 스레드간에 객체를 전달하면 예외가 발생합니다.

MyTextBlock.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
     (Action)(() => { LoggingTextBlock.Text += Message += "\r\n"; })); 

이 문제는 UI 스레드에 고유하다고 생각했지만 분명히 모든 스레드에 적용됩니다. 불행히도 내 사용자 정의 클래스에는 UIElements처럼 호출 할 .Dispatcher() 루틴이 없습니다. 그렇다면 어떻게 객체를 다른 쓰레드에 전달하고 쓰레드를 사용할 수있게할까요?

예를 들어 기본 청취자 클래스는 기본적으로 일부 데이터를 찾고, 이벤트를 발생시키고, 해당 데이터를 전달하는 것입니다. ,

// Just the class for carrying the job data. 
public class JobData 
{ 
    // NOTE: I don't no have trouble accessing these properties from a 
    // different thread 
    public string SomeProperty1 { get; set; } 
    public string SomeProperty2 { get; set; } 
    public string SomeProperty3 { get; set; } 

    // ... 
    // more properties 
    // ... 

    // This a .NET object of type System.Printing.PrintSystemJobInfo. This 
    // is the guy that gives me trouble. Later on, I can't access members 
    // of Job without getting the "The calling thread cannot access this 
    // object because a different thread owns it" error. 
    PrintSystemJobInfo m_Job = null; 
    public PrintSystemJobInfo Job 
    { 
     get 
     { 
      if (m_Job == null) 
      { throw new ArgumentNullException(); } 

      return m_Job; 
     } 

     set { m_Job = value; } 
    } 
} 

다음은 스레드에서 실행되는 클래스의 세그먼트 데이터를 수집하고,에 떨어져 그 데이터를 전달하는 이벤트를 발생 : 다음은 내가 전달하고자하는 데이터 클래스의 세그먼트입니다 듣는 사람.

// Thread who monitors looking for data to package into JobData and send 
// to any listeners. 
public class JobMonitor 
{ 
    public delegate void NewJobEvent(JobData jobStuff); 
    public event NewJobEvent NewJob; 

    // Call this when you have some job data and need to notify listeners 
    private void OnNewJob(object newJobData) 
    { 
     JobData newJobData = (JobData)newJobData; 
     if (NewJob != null) 
     { 
      NewJob(newJobData); 
     } 
    } 

    private void WorkerRoutine() 
    { 
     while(true) 
     { 
      // Wait for data 

      // ... 
      // ... 

      // when data is found 

      JobData myJobData = new JobData(); 
      myJobData.SomeProperty1 = "some data"; 
      myJobData.SomeProperty2 = "some data"; 

      int jobID = GetCurrentJobID(); 
      string printerName = GetCurrentPrinterName(); 

      // .NET class System.Printing.PrintQueue 
      PrintQueue printQueue = new PrintQueue(new PrintServer(), printerName); 

      PrintSystemJobInfo jobInfo = null; 
      jobInfo = printQueue.GetJob(jobID); 

      // This is the guy in my JobData class that I'll have trouble accessing 
      // later on. 
      myJobData.Job = jobInfo; 

      // Time to fire off the event 
      OnNewJob(myJobData); 
     } 
    } 
} 

다음은 JobMonitor 클래스를 인스턴스화하고 이벤트를 캡처하는 클래스의 세그먼트입니다. JobMonitor의 속성 중 하나에 액세스하는 데 문제가 있습니다.

// This class signs up to recieve and process events from the JobMonitor class. 
public class JobProcessor 
{ 
    // this is the method that handles the incoming job events. This is where 
    // i have trouble. 
    private void NewJobEventHandler(JobData newJob) 
    { 
     string temp = newJob.SomeProperty1; // this works fine 

     bool bTemp = newJob.Job.IsPaused; // this throws an exception "The 
              // calling read cannot access this 
              // object because a different thread 
              // owns it" 
    } 

    private JobMonitor m_monitor = null; 
    public JobProcessor() 
    { 
     m_monitor = new JobMonitor(); 

     //attaches a method to handle incoming job events. 
     m_monitor.NewJob += new JobMonitor.NewJobEvent(NewJobEventHandler); 
     m_monitor.Start(); 
    } 
} 

는 그래서 JobProcessor.NewJobEventHandler() 메소드는 내가 예외를 받고 있어요 여기서 "다른 스레드가 그것을 소유하고 있기 때문에 호출 스레드가이 개체에 액세스 할 수 없습니다"입니다. 이 속성과 속성 및 메서드에 액세스 할 수 있어야합니다. 필요한 것을 액세스하려면 무엇을해야합니까?

답변

2

System.Threading에서 제공하는 SyncronizationContext을 살펴볼 것입니다. 이 클래스에는 찾으려는 Dispatcher 스타일을 제공하는 정적 등록 정보 Current이 있습니다.

다른 가능성

당신이 당신의 JobData 클래스를 생성하는 것보다 다른 스레드에서 이벤트를 처리하려면는, 당신은 이벤트 처리기에 PrintSystemJobInfo의 실제 검색을 이동해야 할 수도 있습니다.

또 다른 대안은 System 클래스를 작성한 새 클래스로 추상화하는 것입니다 (스레드 선호도가 없음).

+0

글쎄, 나는 다른 제안이 있는지를보기 위해 조금 기다렸다. "SyncronizationContext"방식은 나에게 열매를 맺지 못했습니다. 나는 개념을 조금 잃어 버렸기 때문에 잘못했을 가능성이 큽니다. 다행스럽게도 PrintSystemJobInfo 객체를 검색하는 것은 쉽고 내 대상 스레드가 이동하여이 객체를 독자적으로 가져올 수있는 충분한 정보가 있습니다. 이상적으로는이 작업을 수행 할 필요가 없으며 대상 스레드는이 정보를 가져 오는 방법을 알 필요가 없습니다. 오 잘, 저를위한 타협의 그것의 큰 아닙니다 그것의 관점에서 두십시오. – Ultratrunks

관련 문제