2017-10-26 1 views
0

winforms 프로젝트에서 폼에 추가 한 두 개의 UserControl이 있습니다. 하나는 문자열을 그리고 오른쪽에서 왼쪽으로 스크롤하고 다른 하나는 스크롤하는 함수입니다 다른 문자열을 그려 아래에서 위로 반복하여 Invalidate()를 while (true) 루프 내에서 호출하여 제어합니다. 그러나 내 문자열 중 하나가 너무 길어서 약 1000 자 UI 스레드가 차단되면 내 질문은 : 내가 뭘 잘못하고 있니? 거기에 텍스트 스크롤을 만드는 더 좋은 방법은 ???문자열이 너무 긴 경우 Onpaint() 블록 UI 스레드에서 문자열을 그립니다.

코멘트에서 언급 한 바와 같이
int scrollTextSpeed = 100; 
bool scrollingText = true; 
Thread updateUI ; 

void init(){ 
    updateUI = new Thread(updateScrollText); 
    updateUI.Start(); 
} 

void updateScrollText() 
    { 
     while (true) 
     { 
      if (scrollingText) { 

       Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, 
       new MethodInvoker(Invalidate)); 
       Thread.Sleep(scrollTextSpeed); 
      } 
     } 
    } 


protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
    { 

     SizeF stringSize = e.Graphics.MeasureString(text, this.Font); 

     var yPos = (this.ClientSize.Height/2) - (stringSize.Height/2); 
     e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias; 
     e.Graphics.DrawString(text, this.Font, brus, 
     currentPos, yPos); 
     if (fisttime) 
     { 
      currentPos = this.ClientSize.Width - 1; 
      fisttime = false; 
     } 
     else 
     { 
      if (currentPos < (-1 * (stringSize.Width))) 
       currentPos = this.ClientSize.Width - 1; 
      else 
       currentPos -= scrollPixelDistance; 
     } 
    } 
+4

통화 중 루프에서 무효화하지 마십시오. 아무 의미가 없습니다. 타이머가 존재합니다. 또한 변경되지 않으면 매번 문자열을 측정 할 필요가 없습니다. 비트 맵으로 유지할 수 있으므로 매번 그리지 마십시오. –

+0

왜 텍스트를 그리는 중입니까? 왜'Label'을 사용하지 않습니까? – Enigmativity

+0

새로운 WinForms 프로젝트에 코드를 복사하여 컴파일하고 50000 자의 문자열로 계속 스크롤하면 양식이 사용자 입력에 계속 응답합니다. –

답변

1

, 나는 UI 스레드가 차단되는 문제를 재현 할 수 없습니다 와 울부 짖는 소리의 코드 내 조각이다. 그러나 나는 당신이 코드의이 부분을 리팩토링해야한다고 생각하는데, 아마도 블로킹 UI 문제를 해결할 것이다.

현재 UI 스레드가 Invalidate() 요청을 처리하기로 결정할 때마다 스크롤 속도가 직접 달라집니다. 또한 하나 이상의 스크롤 텍스트가 있음을 나타내므로이 텍스트의 다른 스크롤 속도를 구성하는 것은 거의 불가능합니다. 당신이 어떤 주어진 시간에 스크롤 텍스트의 위치를 ​​확인할 수 있습니다 수학의 비트, 즉와

: 이제 스크롤 위치가 더 이상 새로 고침 속도에 따라 달라
float x = ClientRectangle.Width - (((uint)Environment.TickCount/40f) % 
     (stringSize.Width + ClientRectangle.Width)); 

, 여러 필요가 없습니다 타이머. 그리고 간단한 System.Windows.Forms.Timer을 사용하면 다른 스레드에서 아무 것도 호출 할 필요가 없습니다.

관련 문제