在我的智能设备应用程序中,我有搜索所有可发现的蓝牙设备并使用Windows Mobile 6.5连接到设备的功能。当我按下按钮搜索蓝牙设备时,UI冻结,我无法做任何其他事情。在找到所有可发现的设备之后,UI再次响应。
我知道我应该使用线程来处理这个问题。但是,我没有成功地让它发挥作用。
这是我用于搜索蓝牙设备的代码。在代码中,我有两个BindingLists。一个是DiscoverableDevices,另一个是ConnectedSEMDevices,它们分别绑定到一个列表框和一个组合框。
private void SearchBTDevices()
{
// Thread thread = new Thread(new ThreadStart(delegate{
List<BluetoothDevice> list = new List<BluetoothDevice>();
this.discoverableDevices.Clear(); //DiscoverableDevices is binding to the form
list.foreach(x => this.Discoverable.Add(x));
ConnectedSEMDevices.Clear()
list.Where(x => x.HasAuthenticated).ToList().ForEach(x => ConnectedSEMDevices.Add(x)); // ConnectedSEMDevices is binding to the Form
// }));
// thread.Start();
}
当我在上面的代码中取消注释掉线程时,它没有做任何事情,也没有找到任何设备。在我评论出该帖子之后,它就有效了。有谁知道原因?我想以与搜索设备相同的形式做其他事情。
答案 0 :(得分:5)
看一下使用BackgroundWorker线程:
我怀疑您遇到的问题是,在您创建的主题中,您正试图将结果立即绑定到UI控件。基本上,当您创建这样的线程时,不允许与任何UI元素通信,因为它们位于不同的线程上。
在您的情况下,我将创建一个BackgroundWorker,将上面的大部分代码放在DoWork方法中,该方法填充您的列表,然后在RunWorkerCompleted方法中绑定您的&#39; Lists&lt;&gt;&#39;到您的用户控件。
Compact Framework 3.5的更新:
您仅限于使用Thread.Start和Timer进行线程处理:
Threading in Compact Framework
这似乎更像你要做的事情:
Microsoft .NET Compact Framework Multi-threading Tips
在这种情况下,我会回到你正在做的事情。我对你的代码片段感到担心的是,似乎没有一个方法调用实际上有你的蓝牙设备的方法。这是我要开始的地方:
private void SearchBTDevices()
{
Thread thread = new Thread(new ThreadStart(delegate
{
List<BluetoothDevice> list = new List<BluetoothDevice>();
// isn't there some method you have that populates your List<BluetoothDevices>????
list = FindMeMyBluetoothDevices();
this.Invoke(new MethodInvoker(() =>
{
this.discoverableDevices.Clear();
list.ForEach(x => this.discoverableDevices.Add(x));
}));
this.Invoke(new MethodInvoker(() =>
{
ConnectedSEMDevices.Clear();
list.Where(x => x.HasAuthenticated).ToList().ForEach(x => ConnectedSEMDevices.Add(x));
}));
}));
thread.Start();
}
答案 1 :(得分:0)
BindingLists修改后立即引发事件。如果您将它们绑定到控件,那么将通知这些控件,但是在错误的线程上。
有两个选项:
1)根据BradRem的回答使用BackgroundWorker。
2)只要您修改绑定到控件的BindingList,就可以在任何时候访问UI控件时调用Invoke。
private void SearchBTDevices()
{
Thread thread = new Thread(new ThreadStart(delegate{
List<BluetoothDevice> list = new List<BluetoothDevice>();
this.Invoke(new MethodInvoker(() => this.discoverableDevices.Clear()); //DiscoverableDevices is binding to the form
list.foreach(x => this.Discoverable.Add(x));
var connectedDevices = list.Where(x => x.HasAuthenticated).ToList());
this.Invoke(new MethodInvoker(() => {
ConnectedSEMDevices.Clear()
ConnectedSEMDevices.AddRange(connectedDevices)));}
}
}));
thread.Start();
}