2012-06-05 30 views
0

我使用SerialPort來獲取來電顯示,當有人打我的座機時。我已經使用PuTTy軟件進行了測試,並且工作正常。使用SerialPort的來電顯示C#

但是,我的C#代碼拋出了一個InvalidOperation異常,並表示:跨線程操作無效:從其創建的線程以外的線程訪問控制lblCallerIDTitle。這個錯誤發生在我嘗試做的時候:lblCallerIDTitle.Text = ReadData;

我該如何解決這個問題?下面是我的代碼:

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 System.IO.Ports; 

namespace CallerID 
{ 
    public partial class CallerID : Form 
    { 
     public CallerID() 
     { 
      InitializeComponent(); 
      port.Open(); 
      WatchModem(); 
      SetModem(); 
     } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     WatchModem(); 
    } 

    private SerialPort port = new SerialPort("COM3"); 
    string CallName; 
    string CallNumber; 
    string ReadData; 

    private void SetModem() 
    { 
     port.WriteLine("AT+VCID=1\n"); 
     port.RtsEnable = true; 
    } 

    private void WatchModem() 
    { 
     port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 
    } 

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     ReadData = port.ReadExisting(); 
     //Add code to split up/decode the incoming data 
     lblCallerIDTitle.Text = ReadData; 
     Console.WriteLine(ReadData); 
    } 

    private void CallerID_Load(object sender, EventArgs e) 
    { 

    } 
    } 
} 

我想要一個標籤來顯示傳入的數據。謝謝

+0

可能重複[ThreadControl.Invoke](http://stackoverflow.com/questions/1423446/thread-control-invoke) –

+0

http://www.yoda.arachsys.com/csharp/threads/winforms。 shtml - 可能這就是你要找的。 –

回答

3

您的用戶控件(如標籤)必須在UI線程上更新,並且串行數據正在另一個線程中。

你的兩個選擇是使用Invoke()將控件更新推送到主UI線程,或讓串行線程更新變量,並使用計時器控件檢查該變量以更新標籤。

第一個(好)選項的代碼,應該是這個樣子:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    ReadData = port.ReadExisting(); 
    //Add code to split up/decode the incoming data 
    if (lblCallerIDTitle.InvokeRequired) 
     lblCallerIDTitle.Invoke(() => lblCallerIDTitle.Text = ReadData); 
    else 
     lblCallerIDTitle.Text = ReadData; 
    Console.WriteLine(ReadData); 
} 

的標籤將被不斷更新的主UI線程。

+0

您可以爲任何一個提供解決方案,因爲我對C#相當陌生。 – Subby

+0

已添加示例代碼。 – MCattle

+0

嗨MCattle。 lblCallerIDTitle.Invoke(()=> lblCallerIDTitle.Text = ReadData);給我提供以下錯誤:無法將lambda表達式轉換爲鍵入'System.Delegate',因爲它不是委託類型 – Subby

2

從另一個線程更新UI時,需要使用Invoke

替換...

lblCallerIDTitle.Text = ReadData 

...與...

lblCallerIDTitle.Invoke(new SetCallerIdText(() => lblCallerIDTitle.Text = ReadData)); 

...這個聲明在某處你的類...之後

public delegate void SetCallerIdText(); 

雖然我更喜歡this question的答案。

+1

lblCallerIDTitle.Invoke((=)=> lblCallerIDTitle.Text = ReadData);給我以下錯誤: 無法將lambda表達式轉換爲類型'System.Delegate',因爲它不是委託類型。 – Subby

+0

非常感謝您的幫助。你能告訴我怎樣才能得到來電號碼,因爲我總是得到字符串「RING RING」。 – Subby

+0

@Subby:你應該問另一個問題 –