2016-10-25 1 views
0

음을, 나는 버튼이있는 Form1을 가지고 있고이 버튼 중 하나를 클릭하면 그것은 Form1에C# 스레딩은 여전히 ​​UI 응답하지

UserControl1을이 데이터베이스와 같은 많은 데이터를 포함

에 패널로 UserControl을로드 것, 차트 및 그림 상자도. 따라서로드하는 동안 사용자 인터페이스가 확실히 응답하지 않게됩니다.

일부 기사를 읽었으므로 다른 스레드를 통해 실행해야한다는 것을 알았 기 때문에 약간의 성능 향상을 보았습니다.

usercontrol1은 약 3-5 초 동안 GUI를 응답하지 않게 만들고 데이터가 커지면 어떻게합니까? 당신이 이것에 대해 좀 도와 경우

private void click_dashb_Click(object sender, EventArgs e) 
    { 

     ParameterizedThreadStart pts = new ParameterizedThreadStart(load_UserControl); 
     Thread t = new Thread(pts); 
     t.Start(); 

     //Animated Picturebox to show user that UI is loading 
     pictureBox1.Enabled = true; 


     hover.Location = new Point(42, 130); 
    } 


    private void load_UserControl(object state) 
    { 

     Invoke(new Action(() => 
     { 
      //load user control through another thread 
      while (panel1.Controls.Count > 0) 
       panel1.Controls[0].Dispose(); 


      Home frm = new Home(); 


      frm.AutoScroll = true; 
      panel1.Controls.Add(frm); 
      frm.Show(); 
     })); 

     //Stop the animated GIF means the load is finish! 
     pictureBox1.Enabled = false; 
    } 

: 그 마무리 로딩 여기

내 코드의 경우

이 나는 ​​반응하고 여전히 애니메이션의 PictureBox를 실행하여로드 사용자에게 표시하고 중지하려면 문제. 나는 모든 작품에 적용 할 수 있습니다. 대부분의 데이터에는 큰 데이터가 포함되어 있기 때문입니다.

덕분에 유래 커뮤니티 :

편집 :

배경 노동자를 사용하는 제안 코멘트를 읽은 후. 나는 그것을 사용하려고 노력했다.

private void click_dashb_Click(object sender, EventArgs e) 
    { 

     bgw.RunWorkerAsync(); 

    } 
private void bgw_DoWork(object sender, DoWorkEventArgs e) 
    { 

     try 
     { 


      BeginInvoke((MethodInvoker)delegate 
      { 
       while (panel1.Controls.Count > 0) 
        panel1.Controls[0].Dispose(); 


       Home frm = new Home(); 


       frm.AutoScroll = true; 
       panel1.Controls.Add(frm); 
       frm.Show(); 
      }); 


     } 
     catch (Exception x) 
     { 
      MessageBox.Show("An error occured while performing operation" + x); 
     } 

    } 

    private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 

    } 

    private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Cancelled) 
     { 
      MessageBox.Show("Operation Cancelled"); 

     } 
     else 
     { 

      MessageBox.Show("Operation Completed"); 


     } 
    } 

그것은 조금 더 나은하지만 난 아직도 조금 무 반응을 얻었다 :하지만 여전히 조금 응답하지 않는 을 받고 여기에 새로운 코드입니다. 내 코드를 확인하고이 코드의 문제점을 찾아 낼 수 있습니까?

다시 한번 감사

+1

Invoke 함수는 기본 AKA UI 스레드에서 실행 된 대리자 매개 변수를 제공합니다. –

+4

그 스레드가 단지 'Invoke'에있는 모든 활동을 감싸고 있다면 새 스레드를 생성 할 필요가 없습니다. Invoke의 요점은 활동을 UI 스레드로 마샬링하는 것입니다. –

+1

BackgroundWorker를 보면이 문제를 해결하기 위해 특별히 설계되었으므로 자체 스레드를 만들 필요가 없습니다. – Paolo

답변

0

코드의 문제는 새로운 스레드에 load_UserControl 코드를 실행하지만, 그 코드를 효과적으로 알 다시 UI 스레드에서 코드를 실행하게하는 호출을 호출하는 것입니다. Forms 및 PictureBox에 액세스하려면 UI 스레드에서 실행해야하므로 이미지를 작성할 수 있습니다.

솔루션은 (일반적으로) 별도의 스레드에서 비 UI 작업을 수행 한 다음 UI 스레드로 다시 전환하여 시각적 컨트롤을 업데이트하는 것입니다.

이렇게하려면 BackgroundWorker 클래스를 편리하게 사용할 수 있습니다. DoWork 이벤트 처리기에서 무거운 계산을 수행하고 RunWorkerCompleted 이벤트 처리기에서 컨트롤을 업데이트합니다. 원하는 경우 ProgressChanged 이벤트 핸들러를 사용하여 작업 중에 진행률 막대와 같은 일부 컨트롤을 업데이트 할 수도 있습니다.

+0

기술적으로 두 가지 형식이 있습니다 (다른 하나는 userControl입니다) 배경 작업자를 어디에서 적용해야합니까? 기본 폼 또는 사용자 정의 컨트롤에? 나는 정확한 포인트를 얻을 수 없기 때문에 나는 지금 당장 @ _ @를 약간 혼동했다.하지만 나는 그 생각을 가지고있다. 바로 지금 '이 배경 작업자를 배울 수있는 기사 또는 코드를 찾고 있습니다. (나는 스레딩을 사용하여이 문제를 해결할 수있을 것이라고 생각했습니다. ( 미안 해요. 나는 신참입니다 –

+0

명백하게 스레드를 만드는 대신 BackgroundWorker를 사용하면 해당 장면에 대한 새로운 스레드가 생성됩니다. DoWork 및 RunWorkerCompleted 이벤트 처리기를 제공 한 다음 해당 개체에서 RunWorkerAsync()를 호출하여 계산을 시작하면됩니다 – Emile

+0

BackgroundWorker MSDN의 클래스 문서를 시작해야합니다. – Emile

0

글쎄, 새 스레드를 시작해도 정의에 따라 UI가 반응하지 않습니다. 스레드가 실제로 병렬 처리되도록 스레드를 만들어야합니다.

스레드는 기본적으로 모든 코드를 this.Invoke에 실행하므로 스레드는 그렇지 않습니다.

귀하의 코드 this.Invoke에서 실행될이 필요합니다. 거의 모든 작업은 UI 스레드에서 수행해야합니다.

UI 스레드를 차단하지 않고 원하는 작업을 수행 할 수있는 방법이 없으므로 스레드 (Threads, Tasks, BackgroundWorker 등)에 대해 알고있는 기술이 없으므로 실제로 병렬화 할 필요가 없습니다. 이 문제를 해결하십시오.

관련 문제