2017-05-30 131 views
0

林有一點麻煩,在我的列表框中顯示的列表。 當我在一堂課中學到了所有東西的時候,事情似乎很順利,但我無法弄清楚它爲什麼現在不起作用。當我點擊掃描按鈕時,我的應用程序會轉到另一個類,其中有一個新線程用於掃描可用的藍牙設備,並創建一個包含這些設備的列表。一旦列表傳遞迴Form1類中的方法,它不會更新列表框。在調試模式下,我可以看到列表中有項目,但列表框中沒有任何內容。如果我通過掃描按鈕單擊方法執行listBox1.Items.Add(「Hello World」),列表框將顯示項目。我有點卡在這裏。我剛開始學習C#,如果有人能幫助我,將不勝感激。無法填充列表框

public partial class Form1 : Form 
{ 
    int PanelWidth; 
    bool PanelCalShow; 

    public Form1() 
    { 
     InitializeComponent(); 
     PanelWidth = PanelCal.Width; 
     PanelCalShow = false;   
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     timer1.Start(); 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     if (PanelCalShow) 
     { 
      PanelCal.Width = PanelCal.Width + 10; 

      if (PanelCal.Width >= PanelWidth) 
      { 
       timer1.Stop(); 
       PanelCalShow = false; 
       this.Refresh(); 
      } 
     } 
     else 
     { 
      if (PanelCalShow != true) 
      { 
       PanelCal.Width = PanelCal.Width - 10; 

       if (PanelCal.Width <= 0) 
       { 
        timer1.Stop(); 
        PanelCalShow = true; 
        this.Refresh(); 
       } 
      } 
     } 
    } 

    // Bluetooth connection 
    private void BtnScan_Click(object sender, EventArgs e) 
    { 
     var instance = new BtCom(); 
     instance.Scan(); 
    }   

    public void LbClientUpdate(List<string> DiscoveredDevices) 
    {       
     listBox1.DataSource = DiscoveredDevices;    
    }   
} 

和藍牙連接類

public class BtCom 
{ 
    public List<string> DiscoveredDevices = new List<string>(); 
    Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB"); 

    public void Scan() 
    {    
     Thread bluetoothScanThread = new Thread(new ThreadStart(Scanning)); 
     bluetoothScanThread.Start(); 
    } 

    BluetoothDeviceInfo[] devices; 

    public void Scanning() 
    {    
     var form1 = new Form1(); 

     BluetoothClient client = new BluetoothClient(); 
     devices = client.DiscoverDevicesInRange(); 

     foreach (BluetoothDeviceInfo d in devices) 
     { 
      DiscoveredDevices.Add(d.DeviceName); 
     }   
     form1.LbClientUpdate(DiscoveredDevices); 
    } 
} 
+0

您有一個函數'LbClientUpdate'來設置ListBox的DataSource,但它不會從任何地方調用。 – James

+1

原因是你沒有看到原始表單上的任何更新,因爲你正在BtCom類中創建一個'Form1'類的新實例,而不是使用原始實例。 –

+0

嗨,對不起。我正在刪除評論,並且必須刪除評論。在listBox1.DataSource之後,我有一個帶有「hello world」的消息框,它彈出時應該像它應該但沒有在列表框中。難道是因爲該方法是從一個不同的線程調用的,它也在該線程中執行,而據我所知,listbox應該在其原始線程內編輯? – Rikas

回答

0

您沒有看到您的原始形態上的任何更新的原因是,你創建BtCom類的內部Form1類的新實例,而不是使用原始實例。

您可以修復此問題的一種方法是將表單的原始實例通過參數傳遞給您的BtClass,然後將其傳遞給Scanning方法。這樣你就可以在運行的窗體的同一個實例上調用方法。

問題在於,當等待線程完成時(假設您調用bluetoothScanThread.Join()來等待線程結果),您將阻塞您的UI。

稍微不同的解決方案是使用Tasks,async方法await結果。

要做到這一點,你會讓你的scan方法返回一個Task<List<string>>(這是一個Task返回代表設備的List<string>)。

然後在form1您可以創建一個async方法(以下稱爲GetDatasource)創建您的BtCom類的實例,awaitsscan方法,並返回Task<List<string>>

最後,您還可以製作Click方法async,並讓它分配等待GetDatasource方法並在返回時指定數據源。

通過這樣做,您可以將BtCon類與必須知道有關Form1類的任何詳細信息分開,因爲您最終創建了更多可重用且獨立的代碼,所以這是一個很好的習慣。

這裏是在代碼中所有這些單詞的一個例子:

充分利用scan方法返回一個可用於數據源一個Task<List<string>>(並有Scanning返回List<string>)。注意列表現在對掃描方法是私有的。將變量的範圍限制在他們所需的級別是一種很好的做法。:

public class BtCom 
{ 
    Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB"); 

    public Task<List<string>> Scan() 
    { 
     var bluetoothScanTask = Task.Factory.StartNew(Scanning); 
     bluetoothScanTask.Wait(); 
     return bluetoothScanTask; 
    } 

    private List<string> Scanning() 
    { 
     BluetoothClient client = new BluetoothClient(); 
     devices = client.DiscoverDevicesInRange(); 

     List<string> discoveredDevices = new List<string>(); 

     foreach (BluetoothDeviceInfo d in devices) 
     { 
      discoveredDevices.Add(d.DeviceName); 
     } 

     return discoveredDevices; 
    } 
} 

然後,寫一個async方法,將通過創建這個類的一個新實例得到的數據源,並await該方法返回。此外,使Click方法異步,因此它可以await數據源方法:

public partial class Form1 : Form 
{ 
    // Other form code omitted... 

    private async void BtnScan_Click(object sender, EventArgs e) 
    { 
     listBox1.DataSource = await Task.Run(GetDatasource); 
    } 

    private async Task<List<string>> GetDatasource() 
    { 
     var btCom = new BtCom(); 
     List<string> results = await btCom.Scan(); 
     return results; 
    } 

現在,用戶可以點擊按鈕和形式將繼續在掃描發生反應,和你的列表框將填充掃描時方法結束。

有關asyncawait的更多信息,請查看您最喜愛的搜索引擎(例如,此頁上的Asynchronous programming)。

+0

非常感謝您的幫助。我今晚下班回家時試試一切。正如我所說的,我剛剛開始使用C#,並且或多或少地將代碼編寫在一起,因此我非常感謝您的幫助。 – Rikas