2012-04-18 2 views
3

스레드의 로컬 서버에서 많은 변수를 읽는 벤치 마크 도구를 프로그래밍하고 있습니다.UI 요소 호출시 스레드가 느리게 실행 됨

  int countReads = 1000; 

      Int64 count = 0; 

      for (int i = 0; i < countReads; i++) 
      { 
       Thread.CurrentThread.Priority = ThreadPriority.Highest; 
       DateTime start = DateTime.Now; 

       session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos); 

       DateTime stop = DateTime.Now; 
       Thread.CurrentThread.Priority = ThreadPriority.Normal; 

       TimeSpan delay = (stop - start); 

       double s = delay.TotalMilliseconds; 
       count += (Int64)s; 

       Dispatcher.Invoke(DispatcherPriority.Render, new Action(() => 
       { 
        progressBar1.Value = i; 
       })); 
      } 

      double avg = (double)count/countReads; 

      Dispatcher.Invoke(DispatcherPriority.Input, new Action(() => 
      { 
       listBox1.Items.Add(avg); 
      })); 

나는 읽기를 계속하고 마지막 평균 소요 시간을 얻는 데 걸리는 시간을 계산합니다.

  DateTime start = DateTime.Now; 

      session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos); 

      DateTime stop = DateTime.Now 

진행률 막대를 업데이트하지 않고 코드를 실행하면 약 5ms 평균이 소요됩니다. 하지만 실행하면

  Dispatcher.Invoke(DispatcherPriority.Render, new Action(() => 
      { 
       progressBar1.Value = i; 
      })); 

평균 약 10ms가 걸립니다.

내 질문은 왜 진행률 막대를 사용할 때 시간 간격이 더 높습니까? 나는 읽기 시간을 계산 중입니다. 진행 표시 줄 업데이트를 포함하지 않습니다.

내 읽기 시간 간격에 영향을 미치지 않도록 ui- 그림을 대피시킬 방법이 있습니까?

도움 주셔서 감사합니다.

안부 현재 실행중인 스레드가 사용하는 디스패처에 연결되어있는 경우

+1

간단한 컨텍스트 스위치, 속성 세트 및 일부 페인트 메시지 발행시 추가 5ms는 오랜 시간이 걸립니다. GUI 메시지 큐가 사용 중입니까? 어쨌든 BeginInvoke를 사용해보십시오. 그렇다면 기다릴 필요가 없습니다. –

+1

DateTime.Now 대신 Stopwatch를 사용하십시오. –

+0

BeginInvoke는 동일한 동작입니다. Thread.sleep (20)을 사용하여 읽기 요청을 바꾸면 timespan은 거의 정확히 20ms이기 때문에 궁금합니다. 진행 바를 사용하거나 사용하지 않고. 그러나 읽기 요청에 대해 더 긴 시간 간격을 갖지 않고 UI를 업데이트 할 수있는 방법이 있습니까? – Destructor

답변

7

Invoke의 사용을 중지하면 진행률 정보가 UI 스레드로 전송됩니다. 공유 데이터 구조 나 변수에 진행 정보를 게시하고 합리적인 간격으로 타이머를 사용하여 UI 스레드가 폴링되도록합니다. 나는 우리 모두가 생각대로 세뇌당한 것처럼 보입니다. Invoke은 worker-to-UI 스레드 상호 작용을위한 모든 방법입니다. 그러나 간단한 진행 정보의 경우 최악의 방법이 될 수 있습니다.

UI 스레드에서 타이머를 사용하는 폴링 방법은 다음과 같은 이점을 제공합니다.

  • Invoke이 UI와 작업자 스레드 모두에 부과하는 단단한 결합이 손상됩니다.
  • UI 스레드는 진행 정보를 업데이트하는시기와 빈도를 지시해야합니다. 당신이 그것에 대해 멈추고 생각할 때 이것이 어쨌든 있어야하는 방법입니다.
  • UI 및 작업자 스레드 모두에서 처리량이 증가합니다.

나는 session.Read이 더 느리게 실행되는 것처럼 보이는 이유에 대해 귀하의 질문에 직접적으로 대답하지 않는다는 것을 알고 있습니다. 푸시 모델 (Invoke 통해)에서 푸시 모델 (타이머를 통해)로 진행 정보 업데이트 전략을 변경하십시오. 차이가 있는지 확인하십시오. 비록 내가 위의 목록에 나와있는 이유로 풀 모델을 고수 할지라도.

+0

이것은 더 나은 전략처럼 들립니다. 간단한 예제가 도움이 될 것입니다. 나는 나 자신을 시도 할 것이다. – Stonetip

0

-이 경우는 비동기 적으로 일을 할 것입니다 Dispatcher.BeginInvoke()을 사용하여 시도 할 수 있도록 Invoke()이 스레드를 차단합니다.

MSDN, Dispatcher.Invoke Method :

호출 동기식 동작이고; 따라서 컨트롤은 콜백이 반환 될 때까지 을 호출 객체에 반환하지 않습니다.

BTW, 단지 관심을 여기에 DispatcherPriority.Send

+0

전 스톱워치를 사용했습니다. 같은 행동. – Destructor

+0

BeginInvoke는 어떻습니까? Invoke는 Dispatcher와 연관된 스레드를 차단합니다. 따라서 현재 스레드가 연관된 경우에 불필요한 시간 초과가 발생했습니다. – sll

+0

OP가 시도했습니다. Invoke/BeginInvoke가 session.read() 호출의 타이밍에 왜 영향을 미치는지에 관해서는 당황 스럽다. OP는 읽기 스레드의 우선 순위를 높입니다. –

1

을 시도 MSDN에 대한 Dispatcher.Invoke

는 Dispatcher가 연결된 스레드에서 동 기적으로 지정된 대리자 을 실행 말씀입니다.

그래서 기본적으로 Dispatcher.Invoke은 디스패처 스레드가 요청을 처리 할 때까지 차단됩니다.

대신 Dispatcher.BeginInvoke을 시도하십시오.

+0

현재 스레드가 Dispatcher와 연결된 경우 – sll

+0

BeginInvoke를 시도하고 동일한 동작을 얻었습니다. 또한 디스패처를 호출하는 부분에서 스레드가 차단되어 있으면 괜찮습니다. 난 그냥 읽기 요청에 대한 부분을 지체없이 작동 싶습니다. GUI가 업데이트를위한 스레드 블록이 읽기에 대한 시간 간격에 영향을 미치지 않아야하거나 잘못된 것인가? – Destructor

+0

오른쪽. 경과 된 시간을 측정하여 10000 회의 판독을 수행하고 결과를 10000으로 나누어 판독 당 더 나은 평균 시간을 얻으십시오. 읽는 것을 하나씩 측정하는 것은 아마 왜 그런 부적절한 결과를 얻었을 것입니다. –

관련 문제