Нужна помощь в работе с потоками в WinForm - PullRequest
0 голосов
/ 20 марта 2012

В моем приложении для смарт-устройств есть функции, которые выполняют поиск на всех обнаруживаемых устройствах Bluetooth и подключаются к устройствам с Windows Mobile 6.5. Когда я нажимаю кнопку для поиска устройств Bluetooth, пользовательский интерфейс зависает, и я больше ничего не могу сделать. После обнаружения всех обнаруживаемых устройств пользовательский интерфейс снова реагирует.

Я знаю, что должен использовать Threading для решения этой проблемы. Тем не менее, у меня нет успеха в том, чтобы заставить его работать.

Вот код, который я использую для поиска устройств Bluetooth. В коде у меня есть два BindingList. Одним из них является 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();
    }

Когда я раскомментирую поток в приведенном выше коде, он ничего не делает, и никакие устройства не обнаруживаются. После того, как я закомментирую тему, она работает. Кто-нибудь знает причину? Я хотел бы сделать что-то еще в той же форме, в которой ищут устройства.

Ответы [ 2 ]

5 голосов
/ 20 марта 2012

Взгляните на использование потока BackgroundWorker:

MSDN - BackgroundWorker

Я подозреваю, что проблема, с которой вы столкнулись, заключается в том, что внутри потока, который вы создаете, выпытаются связать ваши результаты немедленно с вашими элементами управления пользовательского интерфейса.По сути, когда вы создаете такой поток, ему не разрешается общаться с какими-либо элементами пользовательского интерфейса, потому что они находятся в разных потоках.

В вашем случае я бы создал BackgroundWorker, поместив большую часть кода выше вМетод DoWork, который заполняет ваши списки, а затем в методе RunWorkerCompleted связывает ваши «Списки <>» с вашими пользовательскими элементами управления.

Обновление для Compact Framework 3.5:

Выограничено многопоточностью только с Thread.Start и Timer:

многопоточность в Compact Framework

Это больше похоже на то, что вам нужно сделать:

Microsoft .NET Compact Framework Советы по многопоточности

В этом случае я вернусь к тому, над чем вы работали.Что меня беспокоит в вашем фрагменте кода, так это то, что, похоже, не было вызова метода, который фактически получил ваши устройства Bluetooth.Вот где я бы начал:

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();
} 
0 голосов
/ 20 марта 2012

BindingLists вызывают события, как только они изменяются. Если вы связали их с элементами управления, эти элементы будут уведомлены, но не в том потоке.

Два варианта:

1) Используйте BackgroundWorker согласно ответу BradRem.

2) Вызывать Вызывать каждый раз, когда вы получаете доступ к своим элементам управления пользовательского интерфейса И, каждый раз, когда вы изменяете BindingList, связанный с элементом управления.

 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();
}
...