0

TCP 포트에서 스트리밍 데이터를 가져 오는 응용 프로그램을 작성하려고합니다. 실시간으로 계산을 수행합니다. 지금까지는 좋았지 만 프로듀서 스레드가 데이터 청크에서 일부 패키징을 시작하면 사용자 인터페이스 및 선택 윤곽 진행률 막대가 멈 춥니 다 (불규칙하고 단시간). (코드 참조)UI BlockingCollection을 빠르게 사용하면 스레드가 중단됩니까?

 void Produce() 
    { 
     try 
     { 
      while (true) 
      { 
       foreach (Chunk _chunk in bcPort) 
       { 
        if (_ThreadCanceler.IsCancellationRequested) break; 
        Chunk chunk = bcPort.Take(); 
        chunk.TimeTracker = new Stopwatch(); 
        chunk.SegmentId = iSegmentId; 
        if (chunk.Channel + 1 == iChannels) iSegmentId++; // last channel, raise segment id.      
        iPrevChannel = chunk.Channel; 
     //   _ProcessAndJoin.EnqueueTask(chunk, _ThreadCanceler);      
        iChunksProduced++; 
        _LogWriter.WriteMessage("Task " + Task.CurrentId.ToString() + "(producer): ADDED_ Chunk[" + chunk.Channel + ":" + chunk.Vals.Count.ToString() + ":" + chunk.SegmentId + "] [" + iChunksProduced + "]. " + bcPort.Count + " for takeaway. Thread: " + Thread.CurrentThread.ManagedThreadId.ToString()); 
       } 
       if (_ThreadCanceler.IsCancellationRequested) break; 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("ForkAndCrate.cs: Produce(): " + ex.ToString()); 
     } 
    } 

나는 많은 테스트를 수행했으며 BlockingCollection bcPort에 대한 액세스가 문제가되는 것으로 나타났습니다. bcPort는 ui 스레드에 영향을 미치지 않는 다른 데이터 가산기 스레드로부터 지속적으로 청크를 얻습니다. 그래서 나는 다음을 이해하지 못합니다.

1.) 추가 스레드에 청크를 패키징 할 때 GUI가 멈추는 이유는 무엇입니까?

2.) 왜 데이터를 저장하기 위해 BC를 사용할 때 이런 현상이 발생합니까? 이 특정 목적을 위해 이러한 스레드로부터 안전한 컬렉션이 아닙니까?

그런데 : Windows 7 ResourceManager는 스트리밍 중 100 % CPU 사용량을 보여 주며, 청크에는 약 2000 개의 부동 값이 있고 그 중 4 개 또는 5 개는 초당 돌진합니다. 나는 또한 로거를 무효로했지만 효과는 없었다. 소비자 및 평가 스레드는 사용할 수 없습니다.

ui 스레드 외에도 "ReceiveAndSave"라는 스레드 만 들어오는 float 값에서 청크를 만듭니다 (코드, 메서드 "추가"참조). 스레드 "Producer"는 패키징을 추가하고 소비자를위한 청크를 대기열에 넣습니다 (비활성화 됨).

public void Add(short iChannel, float fValue) 
    { 
     try 
     { 
      _Benchmark.UpdateRec(); // one value received, update benchmark: 
      if (!cdBasin[iChannel].Enqueue(fValue)) 
      { 
       Chunk chunk = new Chunk(); 
       chunk.Vals = cdBasin[iChannel].ToListDeep; 
       chunk.Channel = iChannel; 
       bcPort.Add(chunk); 
       cdBasin.AddOrUpdate(iChannel, new BoundedQueue<float>(iSegmentSizePerChannel), (key, oldValue) => new BoundedQueue<float>(iSegmentSizePerChannel)); 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString(), "Stop", MessageBoxButtons.OK, MessageBoxIcon.Stop); 
     } 
    } 

생산자는 myThreads [0] 신규 스레드 (농산물) = '로 시작되며 myThreads [0] .Name = "제작"; myThreads [0] .Start(); '

+0

게시 한 코드가 어디에서 실행되고 있는지 또는 실제로 어떤 스레드에서 진행되고 있는지 명확하지 않습니다 ... 상황을 명확히하십시오. –

+0

add 메소드는 다소 이상하게 보일 것입니다.하지만 청크는 정확히 각각 500 개의 val을 가져야하고, 채널에 연결되어 있어야합니다. 그렇게 많은 데이터가 쇄도하는 것은 쉽지 않습니다. 성능상의 이유로, 나는 그렇지 않습니다. 왜냐하면 그 값이 비싸기 때문에 사전이나 기원전의 제거를 사용하고 싶습니다. 그래서 나는 제거하고 추가하는 대신에 업데이트하고 있습니다. 그러나 add 메소드가 문제가 아니며 제작자가 BlockingCollection 'bcPort'에 액세스하지 않는 한 매우 부드럽고 빠릅니다. – Rome

답변

1

아니요 정말이 작업을 수행하는 데 너무 많은 작업을하고 있습니다. 따라서 입력 및 페인트 알림에 응답하여 우선 순위가 낮은 작업을 처리하지 않게됩니다. 실제로 처럼 보일 것입니다.과 같이 붙어 있기 때문에 사용자가 확실히 그렇게 생각할 것입니다.

키는 인간의 눈에 맞는 속도로 UI를 업데이트하는 것입니다. 초당 25 회의 업데이트 이상으로 흐림을 감지 할 수는 없습니다. 초당 수천 건의 업데이트로 푸시하면 설명하는 동작을 얻게됩니다. 따라서 결과를 수집하고 충분한 시간이 만료 될 때까지 호출/업데이트하지 마십시오. 그리고 일반적으로 사용자가 의미있는 피드백을주기 위해 소모품 단위로 표시하는 정보를 압축하면 초당 수 백 개의 새 항목을 표시하는 목록이 아무에게도 유용하지 않습니다.

+0

감사합니다. 로그 파일은 상황이 올바르게 진행되고 있는지 확인하기위한 도움으로 만 의미가 있습니다. 사용자 의견을 위해 나는 gui에게 처리 된 청크의 벤치 마크를 매초마다 호출하는 평가기를 가지고 있습니다. 그래서 내 문제는 외관상의 문제이며, marquee progressbar는 연속 처리를 표시하는 것이 옳지 않은 것처럼 보입니다. 계산 집약적 인 경우 (내 벤치 마크 외)에 사용자에게 지속적인 진행 상황을 표시하는 다른 좋은 방법이 있습니까? – Rome

+0

간단한 카운터 만 있으면됩니다. 귀하의 스 니펫은 특정 권장 사항을 제시하기에는 너무 불투명합니다. –

관련 문제