2017-02-14 1 views
0

WinForms 응용 프로그램에서 작업하고 응용 프로그램에서 DataGridView 컨트롤을 사용했습니다. 처음에는 10000 개의 행과 50 개의 열을로드했습니다. 내 시나리오는 특정 시간 간격으로 데이터 소스를 업데이트하는 것입니다 (타이머 사용).런타임에 데이터 소스를 업데이트하는 동안 컨트롤이 정지되는 것을 피하려면 어떻게해야합니까?

문제점 : 데이터 소스를 업데이트하는 동안 작업 (cell_click, 스크롤링 등)을 수행 할 때 그리드가 고정/갱입니다.

이 문제를 해결하는 방법? 해결 방법이 있습니까? 제발 당신의 아이디어를 제안 해주세요. 여기

private void timer1_Tick(object sender, EventArgs e) 
    { 
     //try 
     { 
      timer.Stop(); 
      for (int i = 0; i < 10000; i++) 
      { 
       var row = r.Next() % 10000; 
       for (int col = 1; col < 10; col++) 
       { 
        var colNum = r.Next() % 55; 
        if (table != null) 
         table.Rows[row][colNum] = "hi";// r.Next().ToString(); 
       } 
      } 
      table.AcceptChanges(); 
      timer.Start(); 
     } 
    } 

샘플 출력입니다 :

[https://drive.google.com/open?id=0B9MOGv1FOt-TQ1BNZWtnRktxeXc]

감사

여기에 지금까지 내 코드입니다.

+0

얼마나 자주이 데이터 업데이트는? 마무리하는데 보통 얼마나 걸리나요? –

+0

'DataSet'과'DataGridView'는 실시간으로 업데이트되는 수만 개의 행을 위해 설계되지 않은 것 같습니다. 대신 가상화 렌더링을 사용하는 데이터 그리드가 필요하며 이상적으로는 UI와 밀접하게 연결되지 않은 데이터 소스가 필요합니다. – Luaan

+0

BindingSource를 DataGridView의 DataSource로 사용하고 있습니까? – TnTinMn

답변

1

BackgrounWorker를 사용해보십시오.

BackgroundWorker는 작업자 스레드를 관리하기위한 System.ComponentModel 네임 스페이스의 도우미 클래스입니다. 그것은 EAP (이벤트 기반 비동기 패턴)의 범용 구현으로 간주하고 다음 기능을 제공 할 수 있습니다

  • 협력적인 취소 모델

  • 안전하게 업데이트 할 수있는 기능 작업자가 완료 이벤트

  • 진행
  • 보고를위한 프로토콜에 대한 예외의

  • 전달을 완료하면 WPF 또는 Windows Forms 컨트롤
  • 는 비주얼 스튜디오의 디자이너

우는 소리는 예를 찾을 수에 위치를 차지 할 수있게 IComponent의 구현, 당신의 타이머에 적응하십시오

class Program 
{ 
    static BackgroundWorker _bw = new BackgroundWorker(); 

    static void Main() 
    { 
    _bw.DoWork += bw_DoWork; 
    _bw.RunWorkerAsync ("Message to worker"); 
    Console.ReadLine(); 
    } 

    static void bw_DoWork (object sender, DoWorkEventArgs e) 
    { 
    // This is called on the worker thread 
    Console.WriteLine (e.Argument);  // writes "Message to worker" 
    // Perform time-consuming task... 


      //update your grid 
      for (int i = 0; i < 10000; i++) 
      { 
       var row = r.Next() % 10000; 
       for (int col = 1; col < 10; col++) 
       { 
        var colNum = r.Next() % 55; 
        if (table != null) 
         table.Rows[row][colNum] = "hi";r.Next().ToString(); 
       } 
      } 
      table.AcceptChanges(); 

    } 
} 
+3

DataGrid가 데이터 테이블에 데이터 바인딩 된 것처럼 보이기 때문에 이것이 문제를 야기 할 것이라고 확신합니다. 따라서 UI가 아닌 스레드에서 UI 업데이트를 가져올 것입니다. – Luaan

+0

그런 이유로 MainWork를 다시 사용하여 UI를 업데이트 할 수있는 동안 BackgroundWorker를 사용하여 별도의 스레드에서 작업을 실행해야합니다. 좋은 예가 msdn https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx – Zinov

+1

에서 찾을 수 있습니다. msdn의 예에서 UI 요소는 실제로 UI 스레드에서 업데이트됩니다. 이것이 UI 스레드를 호출하는 ReportProgress 함수를 통해 진행 상황이 업데이트되는 이유입니다. ProgressChanged 이벤트 핸들러에 중단 점을 넣고 실행중인 스레드를 확인하여 확인하십시오. 보시다시피, 그것은 주요 실입니다. 따라서 샘플에서 InvalidOperationException이 발생합니다. – sbecker

1

해결 방법 중 하나는 그러한 장기간 작동 중에 Application.DoEvents()을 호출하는 것입니다. 여기에 샘플이 있습니다

private void timer1_Tick(object sender, EventArgs e) 
{ 
    //try 
    { 
     timer.Stop(); 
     for (int i = 0; i < 10000; i++) 
     { 
      var row = r.Next() % 10000; 
      for (int col = 1; col < 10; col++) 
      { 
       var colNum = r.Next() % 55; 
       if (table != null) 
        table.Rows[row][colNum] = "hi";// r.Next().ToString(); 
      } 
      Application.DoEvents(); //add this line 
     } 
     table.AcceptChanges(); 
     timer.Start(); 
    } 
} 

또 다른 해결 방법은 장기 실행 작업을 별도의 스레드로 옮기는 것입니다.

+0

감사합니다. Application.DoEvents()가 어떻게 작동합니까? 왜냐하면 이걸 사용하면 그리드가 업데이트되지 않았기 때문입니다. 그러나 때로는 그리드 값이 몇 개의 컬럼에 대해서만 변경됩니다. – Prithiv

+0

@Prithiv 기본적으로 메시지 루프 반복을 실행합니다. 이것의 가장 큰 문제점은 재발을 허용한다는 것인데, 이는 다소 논리적이지 않습니다. (예를 들어 두 개 이상의 Tick 프로세서가 병렬로 번갈아 실행될 수 있습니다). 그리고 당신이 이런 방향으로 가고 어떤 식 으로든 재임명을 제한하지 않는다면, 당신은 실제로 모든 반복에서 그것을하지 않으려합니다. 그것은 실제로 매우 느려질 수 있습니다. 대신 응용 프로그램이 상당한 시간 (예 : 20-200ms) 동안 응답하지 않는 것을 방지하기에 충분할 때만 수행하십시오. – Luaan

관련 문제