2013-04-17 2 views
1

두 개의 스레드가 실행되는 버튼을 누르면 Windows 양식을 제어하는 ​​주 스레드가 있습니다. 하나는 정보를 기록하는 데 사용되고 다른 하나는 정보를 읽는 데 사용됩니다. 이들을 스레드에 넣는 아이디어는 사용자가 실행 중에 인터페이스와 상호 작용할 수있게하는 것입니다.두 개의 스레드를 시작하면 순서가 아니라 동시에 실행됩니다.

여기에 두 개의 스레드가 생성됩니다.

Thread recordThread = new Thread(() => RecordData(data)); 
recordThread.Name = "record"; 
recordThread.Start(); 

Thread readThread = new Thread(() => ReadData(data)); 
readThread.Name = "read"; 
readThread.Start(); 

데이터 단순히 기록시에 기록되는 데이터를 저장하는 데이터 오브젝트이다.

내가 직면하는 문제는 첫 번째 스레드가 잘 실행되고 두 번째 스레드가 첫 번째 스레드가 완료 될 때까지 실행을 거부한다는 것입니다. 두 번째 스레드 함수에 중단 점을 넣으면 ReadData은 첫 번째 스레드가 모든 기록 작업을 마친 후에 만 ​​호출된다는 사실을 알 수 있습니다.

저는 지금이 문제를 몇 시간 동안 풀려고 노력해 왔으며, 왜 이렇게 할 것인지를 생각할 수 없습니다. 추가; 시작은 그 이후로 아무것도의 실행을 중지되며,이 상태의 직후

while(readThread.IsAlive) { } 

실행 입니다. 그러나 그것은 주어진 방법으로 가지 않을 것입니다.

아이디어가 있으십니까?

: 스레드에 의해 호출되는 두 가지 기능은 다음과 같습니다.

private void RecordData(Data d) 
    { 
     int i = 0; 
     while (i < time * freq) 
     { 
      double[] data = daq.Read(); 
      d.AddData(data); 
      i++; 
     } 
    } 

    private void ReadData(Data d) 
    { 
     UpdateLabelDelegate updateData = 
      new UpdateLabelDelegate(UpdateLabel); 

     int i = 0; 
     while (i < time * freq) 
     { 
      double[] data = d.ReadLastData(); 
      this.Invoke(updateData, new object[] { data }); 
      i++; 
     } 
    } 

데이터 객체 부름 양쪽 기능에 록킹; ReadLastData 및 Read.

다음은 데이터 개체의 메서드입니다.

public void AddData(double[] data) 
    { 
     lock (this) 
     { 
      int i = 0; 
      foreach (double d in data) 
      { 
       movementData[i].Add(d); 
       i++; 
      } 
     } 
    } 

    public double[] ReadLastData() 
    { 
     double[] data = new double[channels]; 
     lock (this) 
     { 
      int i = 0; 
      foreach (List<double> list in movementData) 
      { 
       data[i] = list[list.Count - 1]; 
      } 
     } 
     return data; 
    } 
+2

두 번째 스레드가 첫 번째 스레드에 의해 잠긴 리소스를 기다리고 있는지 여부에 따라 다릅니다 ('데이터'추측). 너는 어떤 잠금 장치를 가지고 있니? – Belogix

+3

문제를 보여주는 짧지만 완전한 * 프로그램을 보여주십시오. –

+2

더 많은 코드를 보여주십시오, 이것은 충분하지 않습니다 –

답변

1

외모 : 는이 같은 통화를 시도 할 수 당신은 당신의 읽기/쓰기 사이에서 경쟁 조건을 가지고있는 것처럼 말입니다. 첫 번째 스레드에서는 데이터를 추가하는 동안 객체를 잠그고 두 번째 스레드에서는 시도를 독점적으로 잠그기 위해을 시도합니다. 그러나 문제는 첫 번째 스레드가 너무 빨리 실행되어 두 번째 스레드가 실제로 잠금을 획득 할 기회를 얻지 못한다는 것입니다.

이 문제에 대한 해결책은 실제로 어떤 종류의 동작을하는지에 따라 다릅니다. 매번 쓰기를 할 때마다 연속적인 읽기를 기대한다면, 당신이해야 할 일은 읽기/쓰기 작업 사이의 실행을 제어하는 ​​것입니다.

static AutoResetEvent canWrite = new AutoResetEvent(true); // default to true so the first write happens 
static AutoResetEvent canRead = new AutoResetEvent(false); 
... 
private void RecordData(Data d) 
{ 
    int i = 0; 
    while (i < time * freq) 
    { 
     double[] data = daq.Read(); 
     canWrite.WaitOne(); // wait for the second thread to finish reading 
     d.AddData(data); 
     canRead.Set(); // let the second thread know we have finished writing 
     i++; 
    } 
} 

private void ReadData(Data d) 
{ 
    UpdateLabelDelegate updateData = 
     new UpdateLabelDelegate(UpdateLabel); 

    int i = 0; 
    while (i < time * freq) 
    { 
     canRead.WaitOne(); // wait for the first thread to finish writing 
     double[] data = d.ReadLastData(); 
     canWrite.Set(); // let the first thread know we have finished reading 
     this.Invoke(updateData, new object[] { data }); 
     i++; 
    } 
} 
+0

이것은 기능 발사의 문제를 해결 한 것 같습니다! 좋은! 유일한 문제는 이것이 시스템이 너무 느려서 제대로 작동하지 못하게하는 것입니다. 매 10 분의 1 값을 읽으면서 테스트를 시작할 것입니다. 하지만 이것이 또 다른 문제입니다. 이것이이 질문에 대한 해결책입니다. 감사! – Sander

+0

@Sander 정확히 무슨 일이 일어나야합니까? 쓰기 도중 실제로 읽어야합니까? [lock 문] (http://msdn.microsoft.com/en-gb/library/c5kehkcz(v=80) .aspx)을 사용하는 것에 대한 FYI - 유형 자체를 잠그지 않는 것이 좋습니다. 즉, 잠금 (this) '은 지침을 위반합니다. 대신에 * data * 인스턴스 외부에 잠금 객체가 있어야합니다 (필자의 예제에서'AutoResetEvent'를 사용하는 것과 비슷합니다). 실제로 근본적인 문제가 여기에 있는지 확인할 수 있습니다. – James

+0

이전에 언급했듯이 코드를 변경 한 것이 좋았던 코드로 변경되었지만 너무 느립니다. 데이터 수집 카드에서 실시간으로 데이터를 가져 와서 사용자에게 제공합니다.이것이 내가 쓰는 동안 데이터를 읽는 이유입니다. 기록을 통해 얻은 정보가 읽음보다 더 중요하므로 읽는 동안 기록의 우선 순위를 어떻게 결정해야하는지 파악해야합니다. – Sander

0

잠자기를 RecordData에 추가 할 수 있습니까? 어쩌면 두 번째 스레드가 CPU 리소스를 사용하지 못하게하는 것은 (모노 CPU?) Windows 운영 체제 일 수 있습니다.

이하지 마십시오 잠금 (이)

이 대신 같은 것을 수행

private object oLock = new object(); 

[...] 

lock (this.oLock) 

이 편집 :

Thread recordThread = new Thread((o) => RecordData((Data)o)); 
recordThread.Name = "record"; 
recordThread.Start(data); 
+0

4 개의 코어가있는 시스템을 실행 중입니다. 그리고 내 이해로 여러 스레드가 단일 코어에서도 실행할 수 있어야합니다. 그러나 어쨌든, 제 경우에는 정말로 문제가되지 않아야합니다. (편집 : 잊어 버린 "하지") – Sander

+0

오키, 고마워. 그러나 문제는 지속됩니다. – Sander

+0

oLock 이벤트가 변경 되었습니까? :/ – Serge

관련 문제