Reputation: 465
I'm using A background worker for BLE RSSI level test.
my problem is that RunWorkerCompleted event is fired immediately, way before DoWork done it's operation.
most of the DoWork event operation is to create an advertisement watcher and wait for Signal from A Bluetooth low energy device. 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!
Upvotes: 3
Views: 2802
Reputation: 456322
I agree with the other answer that BackgroundWorker
is not compatible with async
/await
. However, I disagree that the simplest solution is to remove async
in favor of BackgroundWorker
. IMO, the superior solution (also resulting in simpler code) is to remove BackgroundWorker
in favor of async
; specifically, to replace the outdated BackgroundWorker
with the superior Task.Run
:
// `worker` is now `Task`.
await Task.Run(() => callTestBLE());
finalizeBleTest();
where the signature of callTestBLE
is async Task
, not async void
.
Upvotes: 9
Reputation: 9575
The problem here with the async
and await
. BackgroundWorker is a bit outdated and do not support asynchronous code. 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.
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.
Upvotes: 3