无法填充列表框

时间:2017-05-30 23:12:59

标签: c# bluetooth listbox

我在列表框中显示列表时遇到了一些麻烦。 当我把所有东西放在一个班级时,事情似乎工作正常,但我无法弄清楚它为什么现在不起作用。我的应用程序在单击扫描按钮时会转到另一个类,其中创建了一个新线程来扫描可用的蓝牙设备,并创建了包含这些设备的列表。将列表传递回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);
    }
}

1 个答案:

答案 0 :(得分:0)

您没有在原始表单上看到任何更新的原因是您正在Form1类内部创建BtCom类的新实例,而不是使用原始实例。

解决此问题的一种方法是将表单的原始实例通过Scan方法的参数传递给BtClass,然后将其传递给Scanning方法。这样,您将在正在运行的表单的同一实例上调用方法。

问题是你在等待线程完成时会阻塞你的UI(假设你调用bluetoothScanThread.Join()来等待线程结果)。

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

要执行此操作,您的scan方法会返回Task<List<string>>Task,返回代表设备的List<string>

然后在form1中,您将创建一个async方法(下面称为GetDatasource),该方法会创建BtCom类的实例,awaits scan 1}}方法,并返回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上的此页面)。