我在列表框中显示列表时遇到了一些麻烦。 当我把所有东西放在一个班级时,事情似乎工作正常,但我无法弄清楚它为什么现在不起作用。我的应用程序在单击扫描按钮时会转到另一个类,其中创建了一个新线程来扫描可用的蓝牙设备,并创建了包含这些设备的列表。将列表传递回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 :(得分: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;
}
现在,您的用户可以点击该按钮,表单将在扫描发生时继续响应,并且您的列表框将在扫描方法完成时填充。
有关async
和await
的详情,请查看您最喜欢的搜索引擎(例如Asynchronous programming上的此页面)。