简体   繁体   English

在异步作废Dowork事件之前触发RunWorkerCompleted

[英]RunWorkerCompleted fired before async void Dowork event

I'm using A background worker for BLE RSSI level test. 我正在使用背景工进行BLE RSSI级别测试。

my problem is that RunWorkerCompleted event is fired immediately, way before DoWork done it's operation. 我的问题是RunWorkerCompleted事件在DoWork完成操作之前立即被触发。

most of the DoWork event operation is to create an advertisement watcher and wait for Signal from A Bluetooth low energy device. DoWork事件的大多数操作是创建广告观察程序,并等待来自低功耗蓝牙设备的信号。 the signal level will be updated fromthe main thread and handling of the result will be on the background worker. 信号电平将从主线程进行更新,结果的处理将在后台工作程序中进行。

here is when I call the Background worker: 这是我给背景工作者打电话的时候:

 ...
  worker = new BackgroundWorker();
        worker.DoWork += callTestBLE;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.RunWorkerAsync(RSSI_Label);
  }

The event handlers: 事件处理程序:

private async void callTestBLE(object sender, DoWorkEventArgs e)
    {
            BluetoothLEAdvertisementWatcher watcher1 ;
            BluetoothLEAdvertisementFilter advertisementFilter1;
            int rssiRetries1 = RSSIRETRIES;
            RssiValue = "";

            advertisementFilter1 = new BluetoothLEAdvertisementFilter();
            try
            {
                advertisementFilter1.Advertisement.LocalName = myUswm.getAdvetrismentName();
                checkRSSI = true;
            }
            catch (Exception) { checkRSSI = false; return; }

            watcher1 = new BluetoothLEAdvertisementWatcher(advertisementFilter);
            watcher1.ScanningMode = BluetoothLEScanningMode.Active;
            watcher1.Received += OnAdvertisementReceived;
            // Wait 5 seconds to make sure the device is really out of range
            watcher1.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);
            watcher1.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);

            try
            {
                watcher1.Start(); 
                await testBLEAsync();
                if (myUswm.getConnectionStatus() == DISCONNECTED)
                {
                    checkNextUUTClick(new object(), new RoutedEventArgs()); return;
                }
                for (int i = 0; i < 5; i++)
                {
                    // if (RssiSamplesNum <= 0 || --rssiRetries < 0)
                    if (RssiSamplesNum <= 0 || --rssiRetries1 < 0)
                    {
                        //serviceList.Clear();
                        watcher1.Stop();
                        rssiRetries1 = RSSIRETRIES;
                        RssiSamplesNum1 = numOfAdvertismentSamples;
                        break;
                    }
                    else
                    {
                       ((Label)e.Argument).Content = RssiValue;
                        /*RSSI_Label.Dispatcher.Invoke(new Action(() =>
                        { RSSI_Label.Content = RssiValue; }));*/
                    }
                    Thread.Sleep(2000);
                  }    
            }
    catch (Exception err) { }
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
       finalizeBleTest();
    }

Thanks for any help! 谢谢你的帮助!

The problem here with the async and await . 这里的问题与asyncawait BackgroundWorker is a bit outdated and do not support asynchronous code. BackgroundWorker有点过时了,不支持异步代码。 So when you await for testBLEAsync call, callTestBLE method finishes and at that moment you have your RunWorkerCompleted event called, while actual code continue to work in the background. 因此,当您等待testBLEAsync调用时, callTestBLE方法完成,并且此时您已调用RunWorkerCompleted事件,而实际代码继续在后台运行。

So simplest solution is to completely remove async / await from your code and everything should work as expected, or, alternatively, you can rewrite your code using tasks and task continuations. 因此,最简单的解决方案是从代码中完全删除async / await ,一切都将按预期工作,或者,您也可以使用任务和任务延续来重写代码。

I agree with the other answer that BackgroundWorker is not compatible with async / await . 我同意BackgroundWorkerasync / await不兼容的另一个答案。 However, I disagree that the simplest solution is to remove async in favor of BackgroundWorker . 但是,我不同意最简单的解决方案是删除async ,而使用BackgroundWorker IMO, the superior solution (also resulting in simpler code) is to remove BackgroundWorker in favor of async ; IMO的高级解决方案(也导致更简单的代码)是删除BackgroundWorker ,而支持async specifically, to replace the outdated BackgroundWorker with the superior Task.Run : 具体来说, 用高级Task.Run替换过时的BackgroundWorker

// `worker` is now `Task`.
await Task.Run(() => callTestBLE());
finalizeBleTest();

where the signature of callTestBLE is async Task , not async void . 其中callTestBLE的签名是async Task ,而不是async void

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM