2013-07-17 4 views
0

데이터베이스에서 값을 선택하고 거기에서 그래프를 계속 업데이트하려고합니다.. How to update the GUI from another thread in C#? 내 코드를 사용하여입니다 : 내가 어떤 오류가 발생하지 않지만데이터베이스에서 값을 선택하는 동안 그래프 업데이트

private void button1_Click(object sender, EventArgs e) 
     { 
       string myConnection = "datasource=localhost;port=3306;username=root;password=root"; 
       MySqlConnection conDataBase = new MySqlConnection(myConnection); 
       MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase); 
       MySqlDataReader myReader; 
       this.Invoke((MethodInvoker)delegate 
       { 
        try 
        { 
         conDataBase.Open(); 
         myReader = cmdDataBase.ExecuteReader(); 

         while (myReader.Read()) 
         { 
          this.chart1.Series["Series1"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp")); 

         } 

         conDataBase.Close(); 
        } 
        catch (Exception ex) 
        { 
         MessageBox.Show(ex.Message); 
        } 
       }); 
     } 

, 난 그래프는 정적/일정으로 그 작업을 것 같아요. 제안 사항. 기본적으로이 그래프는 데이터베이스의 새 값을 기반으로 업데이트를 계속한다는 것입니다. 하트 비트 모니터 또는 그 효과와 같은 것입니다.

어떤 제안 ... 감사합니다

편집 : 나는 또한 배경 노동자를 사용하려고했지만이 또한 내가 버튼을 클릭에서 다음을 얻을 :

Cross thread operation not valid: Control 'charTemperature' accessed from athread other than the thread it was created on 

코드 :

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using MySql.Data.MySqlClient; 
using System.Threading; 

namespace project 
{ 
    public partial class Form2 : Form 
    { 

     private BackgroundWorker bw = new BackgroundWorker(); 

     public Form2() 
     { 
      InitializeComponent(); 
      bw.WorkerSupportsCancellation = true; 
      bw.WorkerReportsProgress = false; 
      bw.DoWork += new DoWorkEventHandler(bw_DoWork); 

     } 

     private void btnExit_Click(object sender, EventArgs e) 
     { 
      Application.Exit(); 
     } 

     private void btnTemperature_Click(object sender, EventArgs e) 
     { 
      if (bw.IsBusy != true) 
      { 
       bw.RunWorkerAsync(); 
      } 


      //this.Invoke((MethodInvoker)delegate 
      // { 
      /* string myConnection = "datasource=localhost;port=3306;username=root;password=root"; 
       MySqlConnection conDataBase = new MySqlConnection(myConnection); 
       MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase); 
       MySqlDataReader myReader; 
        try 
        { 
         conDataBase.Open(); 
         myReader = cmdDataBase.ExecuteReader(); 

         while (myReader.Read()) 
         { 
          this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp")); 

         } 

         conDataBase.Close(); 
        } 
        catch (Exception ex) 
        { 
         MessageBox.Show(ex.Message); 
        } 
       //});*/ 
     } 

     private void btnStopUpdating_Click(object sender, EventArgs e) 
     { 
      if (bw.WorkerSupportsCancellation == true) 
      { 
       bw.CancelAsync(); 
      } 
     } 

     private void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 

      while (true) 
      { 
       if ((worker.CancellationPending == true)) 
       { 
        e.Cancel = true; 
        break; 
       } 
       else 
       { 
        string myConnection = "datasource=localhost;port=3306;username=root;password=root"; 
        MySqlConnection conDataBase = new MySqlConnection(myConnection); 
        MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase); 
        MySqlDataReader myReader; 
        try 
        { 
         conDataBase.Open(); 
         myReader = cmdDataBase.ExecuteReader(); 

         while (myReader.Read()) 
         { 
          this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp")); 
          System.Threading.Thread.Sleep(1000); 

         } 

         conDataBase.Close(); 
        } 
        catch (Exception ex) 
        { 
         MessageBox.Show(ex.Message); 
        } 
       } 
      } 
     } 

     private void Form2_Load(object sender, EventArgs e) 
     { 

     } 


    } 
} 

한 가지 더 쓸데없는 시도 ... 버튼 클릭시 아무런 변화가 없습니다 ...

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using MySql.Data.MySqlClient; 
using System.Threading; 


namespace project 
{ 
    public partial class Form2 : Form 
    { 

     private BackgroundWorker bw = new BackgroundWorker(); 

     public string vdatetime; 
     public Int32 vtemp; 

     public Form2() 
     { 
      InitializeComponent(); 
      bw.WorkerSupportsCancellation = true; 
      // bw.WorkerReportsProgress = false; 
      bw.DoWork += new DoWorkEventHandler(bw_DoWork); 


     } 

     private void btnExit_Click(object sender, EventArgs e) 
     { 
      Application.Exit(); 
     } 

     private void btnTemperature_Click(object sender, EventArgs e) 
     { 
      //if (bw.IsBusy != true) 
      //{ 
       this.bw.RunWorkerAsync(); 
      //} 


      //this.Invoke((MethodInvoker)delegate 
      // { 
      /* string myConnection = "datasource=localhost;port=3306;username=root;password=root"; 
       MySqlConnection conDataBase = new MySqlConnection(myConnection); 
       MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase); 
       MySqlDataReader myReader; 
        try 
        { 
         conDataBase.Open(); 
         myReader = cmdDataBase.ExecuteReader(); 

         while (myReader.Read()) 
         { 
          this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp")); 

         } 

         conDataBase.Close(); 
        } 
        catch (Exception ex) 
        { 
         MessageBox.Show(ex.Message); 
        } 
       //});*/ 
     } 

     private void btnStopUpdating_Click(object sender, EventArgs e) 
     { 
      // if (bw.WorkerSupportsCancellation == true) 
      //{ 
       this.bw.CancelAsync(); 
      //} 
     } 

     private void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 

       if ((worker.CancellationPending == true)) 
       { 
        e.Cancel = true; 
        //break; 
       } 
       else 
       { 
        string myConnection = "datasource=localhost;port=3306;username=root;password=root"; 
        MySqlConnection conDataBase = new MySqlConnection(myConnection); 
        MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase); 
        MySqlDataReader myReader; 
        try 
        { 
         conDataBase.Open(); 
         myReader = cmdDataBase.ExecuteReader(); 
         //this.Invoke((MethodInvoker)delegate 
         //{ 

          while (myReader.Read()) 
          { 
           vdatetime = myReader.GetString("datetime"); 
           vtemp = myReader.GetInt32("temp"); 
           //Thread.Sleep(300); 

    //       this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp")); 
    //        System.Threading.Thread.Sleep(1000); 

          } 

          conDataBase.Close(); 
//      }); 
        } 
        catch (Exception ex) 
        { 
         MessageBox.Show(ex.Message); 
        } 


       } 
     } 

     private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if (e.Cancelled) 
      { 
       // The user canceled the operation. 
       MessageBox.Show("Operation was canceled"); 
      } 
      else if (e.Error != null) 
      { 
       // There was an error during the operation. 
       string msg = String.Format("An error occurred: {0}", e.Error.Message); 
       MessageBox.Show(msg); 
      } 
      else 
      { 
       this.chartTemperature.Series["Temperature"].Points.AddXY(vdatetime, vtemp); 
      } 
     } 
     private void Form2_Load(object sender, EventArgs e) 
     { 

     } 

    } 
} 

답변

0

확인이이 작업을 수행합니다 시스템을 사용하여

; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; MySql.Data.MySqlClient; using System.Threading;

네임 스페이스 프로젝트 { 공공 부분 클래스 형식 2 : 양식 {

public delegate void AddGraphPointsTemp(); 
    public AddGraphPointsTemp myDelegate1; 
    Thread tempThread; 
    string myConnection; 
    MySqlConnection conDataBase; 
    MySqlCommand cmdDataBase; 
    MySqlDataReader myReader; 


    public Form2() 
    { 
     InitializeComponent(); 

     myDelegate1 = new AddGraphPointsTemp(AddGraphPointsMethodTemp); 
     myConnection = "datasource=localhost;port=3306;username=root;password=root"; 
     conDataBase = new MySqlConnection(myConnection); 
     cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase); 
     conDataBase.Open(); 
     myReader = cmdDataBase.ExecuteReader(); 


    } 

    private void btnExit_Click(object sender, EventArgs e) 
    { 
     conDataBase.Close(); 
     Application.Exit(); 
    } 

    public void AddGraphPointsMethodTemp() 
    { 
     try 
     { 

       myReader.Read(); 
       chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp")); 
       chartTemperature.Update(); 




     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 


    } 

    private void btnTemperature_Click(object sender, EventArgs e) 
    { 
     tempThread = new Thread(ThreadFunction1); 
     tempThread.Start(this); 

    } 


    public static void ThreadFunction1(Object obj) 
    { 
     while (true) 
     { 
      Form2 myForm2 = (Form2)obj; 
      myForm2.Invoke(myForm2.myDelegate1); 
      Thread.Sleep(300); 
     } 
    } 


    private void Form2_Load(object sender, EventArgs e) 
    { 

    } 

} 

}

내가 호출 또는 BackgroundWorker에
0

변경 사항 알림을 클라이언트에 전달할 방법이 없다고 가정 할 때 어떤 종류의 폴링 방식이 필요할 수 있습니다.

타이머를 설정하고 (아래 링크 참조) 경과 된 간격으로 새 데이터를 쿼리 할 수 ​​있습니다.
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx

은 당신이 사용하는 차트의 종류를 모르겠어요,하지만 당신은 시리즈의 마지막에 새로운 포인트를 추가 할 수 있습니다 (그리고 시리즈의 전면에서 오래된 것들을 제거)하는 줄 수도 있습니다 당신이 언급 한 박력 넘치는 모니터 효과와 같은 것입니다. (차트가 지원하지 않으면 다시 작성해야하거나 각 업데이트에 완전히 새로운 시리즈를 제공해야합니다)

사용중인 쿼리를 조정하여 각 호출에서 새 데이터 포인트 만 가져옵니다. (여기서 datetime> [이전 호출에서 이미 검색 한 최대 날짜 시간])

실제로 여전히 귀하의 질문에 설명 된대로 호출 (..)를 통해 호출 할 수있는 UI 업데이트를 수행하는 코드 ...

+0

Invoke ...하지만 독자적으로 코드가 실행됩니다.타이머가 사용될 수있는주기적인 업데이트를 트리거하기위한 무언가가 필요합니다 (다른주기적인 이벤트를 첨부하지 않는 한) ... 타이머 이벤트가 Invoke 코드를 호출 할 수 있습니다 ... BackgroundWorker는 데이터 검색을 다른 스레드로 푸시하려는 경우 (작업자가 완료되면 UI 새로 고침을 트리거 할 수 있음) – Why

+1

당신은 사용할 수 있습니다 중 하나를 사용할 필요가 ... 타이머를 사용하려는 해달라고 –

+1

업데이트 된 질문보기. 나는 백그라운드 작업자에서 반복 및 수면을 볼 수 있습니다. 올바른 스레드에서 UI 업데이트 코드를 가져올 필요가 ... DoWork 메서드 내에서 this.chartTemperature 변경 주위에 Invoke 호출을 시도 할 수 있습니다 ... 그러나 이것은 BackgroundWorker (일반적으로 루프의 비정상적인 사용이라고 생각합니다 수면은 타이머처럼 행동하게 만든다.) –