2015-04-23 68 views
1

因此,我有這個從Arduino獲取值(6個變量)的C#應用​​程序。最初我使用了一個計時器,每100ms調用一次讀取函數,但它會掛起我的用戶界面,並且響應有點沉重。我想使用一個連續讀取這些變量的背景工作。我將這些讀取的調用放在DoWork方法中,並將值放入C#中的變量中,並將它們分配到標籤中。但它不起作用。 (對不起,我的英語)C# - backgroundworker通過串行從Arduino連續獲取數據

namespace testtemp 
{ 
    public partial class tempreaderform : Form 
    { 
     public tempreaderform() 
     { 
      InitializeComponent(); 
     } 

communicator comport = new communicator(); 
Boolean portConnection = false; 
String red_light1; 

private void button1_Click(object sender, EventArgs e) 
     { 
      if (comport.connect(57600, "I'M ARDUINO", 4, 8, 16)) 
      { 
       label1.Text = "Connection Successful - Connected to "+comport.port; 
       portConnection = true; 
       backgroundWorker1.RunWorkerAsync(); // I am not sure if here I should start the backgroundworker. 
      } 
      else 
      { 
       label1.Text = "Not connected . . . "; 
       portConnection = false; 
      } 
     } 

     private void groupBox1_Paint(object sender, PaintEventArgs e) 
     { 
      Graphics ellipse1 = groupBox1.CreateGraphics(); 

      Brush red_on = new SolidBrush(Color.Red); 
      Brush red_off = new SolidBrush(Color.DarkRed); 

      label2.Text = "Red : " + red_light1; //Here is a label which I want to show "1" if "red_light1" is "1" and "0" if "red_light1" is "0" 

      if (red_light1 == "1") ellipse1.FillEllipse(red_on, 250, 133, 24, 24); 
          else ellipse1.FillEllipse(red_off, 250, 133, 24, 24); // Here is what I really want to do (the label.Text part was only to see the value) I want to color a ellipse depending on "red_light1" value. 

     } 



private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      while (true) 
      { 
       red_light1 = comport.message(4, 8, 32); 
      } 
     } 
} 
} 
} 

注:我的DoWork方法tryied這個「label1.Text = red_light1」,但它說,我不能在另一個線程創建的變量給值,這樣的事情。

+0

你把backgroundWorker1_DoWork在另一個線程裏面E類功能? – Thealon

+0

我不確定我是否理解你。我第一次做這個。我相信我在DoWork方法中添加的代碼會在另一個線程中自動「工作」。 – user3672802

+0

那麼這個while循環將永遠不會結束,因此它將永遠停留在那裏。請看看這裏:https://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx。 – Thealon

回答

1

「問題」是背景工作者生活在另一個線程中,而您嘗試在UI線程中使用它。而這條消息並沒有在那裏傳達。

有三個選項:

  1. 要使用RunWorkerCompleted事件:你必須使用一個計時器來運行的BackgroundWorker每隔X毫秒。

    private void timer1_Tick(object sender, EventArgs e) { 
        this.backgroundworker.RunWorkerAsync(); 
    } 
    
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
        e.Result = comport.message(4, 8, 32); 
    } 
    
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
        label2.Text = e.Result.ToString(); 
    } 
    
  2. 使用BeginInvoke設置文本

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
        while (true) 
        { 
         this.BeginInvoke((Action)(() => { label2.Text = comport.message(4, 8, 32); }); 
    
         // add some delay here as well... 
        } 
    } 
    
  3. 使用Task而不是BackgroundWorker的,並調用它的計時器。

    private void timer1_Tick(object sender, EventArgs e) { 
        Task.Run(() => { 
        this.BeginInvoke((Action)(() => { label2.Text = comport.message(4, 8, 32); }); 
        }); 
    } 
    
+0

非常感謝您解釋。我會選擇第一個選項,但我有6個或更多的變量。我應該這樣做6次(因此會是6個線程?)。我也試了你的2選項,我的電腦幾乎爆炸:)),只是開玩笑,但我必須削減權力。我不知道是什麼問題。而我認爲的第三種選擇將採取相同的行動。請給我建議。 – user3672802

+0

我會選擇第三個選項,因爲它很輕便。沒有問題。 2是(我在這裏猜測)你沒有添加任何延遲(見代碼中的評論),並且它一直在處理器上。 –

+0

我在DoWork Method中添加了延遲,但我不確定它是否以正確的方式。 while(true) this.BeginInvoke((Action)(()=> {label2.Text = comport。消息(4,8,32); })); Thread.Sleep(200); }但是用這種方式,沒有背景工作者的用戶界面會比較慢。 – user3672802

1

可以使用ReportProgress事件:

  1. 設置WorkerReportsProgress爲true

  2. 寫事件處理程序:

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
        String mytext = e.UserState as String; 
        myLabel.Text = mytext; 
    } 
    
  3. 個電話在DoWork的

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
        BackgroundWorker bgw = sender as BackgroundWorker; 
        String receivedtext; 
        while (true) 
        { 
         myreceivedtext = comport.message(4, 8, 32); 
         bgw.ReportProgress(0, myreceivedtext); 
         System.Threading.Thread.Sleep(100); 
        } 
    }