RunWorkerCompleted 在 async void Dowork 事件之前触发
RunWorkerCompleted fired before async void Dowork event
我正在使用后台工作者进行 BLE RSSI 级别测试。
我的问题是 RunWorkerCompleted 事件被立即触发,远远早于 DoWork 完成它的操作。
大部分 DoWork 事件操作是创建广告观察器并等待来自低功耗蓝牙设备的信号。
信号电平将从主线程更新,结果处理将在后台工作。
这是我调用后台工作程序的时间:
...
worker = new BackgroundWorker();
worker.DoWork += callTestBLE;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync(RSSI_Label);
}
事件处理程序:
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();
}
感谢您的帮助!
async
和 await
的问题。 BackgroundWorker 有点过时,不支持异步代码。因此,当您等待 testBLEAsync
调用时,callTestBLE
方法完成,此时您的 RunWorkerCompleted
事件被调用,而实际代码继续在后台工作。
最简单的解决方案是从您的代码中完全删除 async
/await
,一切都应该按预期工作,或者,您可以使用任务和任务延续重写代码。
我同意 BackgroundWorker
与 async
/await
不兼容的另一个答案。但是,我不同意最简单的解决方案是删除 async
以支持 BackgroundWorker
。 IMO,更好的解决方案(也导致更简单的代码)是删除 BackgroundWorker
以支持 async
;具体来说,replace the outdated BackgroundWorker
with the superior Task.Run
:
// `worker` is now `Task`.
await Task.Run(() => callTestBLE());
finalizeBleTest();
其中 callTestBLE
的签名是 async Task
,而不是 async void
。
我正在使用后台工作者进行 BLE RSSI 级别测试。
我的问题是 RunWorkerCompleted 事件被立即触发,远远早于 DoWork 完成它的操作。
大部分 DoWork 事件操作是创建广告观察器并等待来自低功耗蓝牙设备的信号。 信号电平将从主线程更新,结果处理将在后台工作。
这是我调用后台工作程序的时间:
...
worker = new BackgroundWorker();
worker.DoWork += callTestBLE;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync(RSSI_Label);
}
事件处理程序:
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();
}
感谢您的帮助!
async
和 await
的问题。 BackgroundWorker 有点过时,不支持异步代码。因此,当您等待 testBLEAsync
调用时,callTestBLE
方法完成,此时您的 RunWorkerCompleted
事件被调用,而实际代码继续在后台工作。
最简单的解决方案是从您的代码中完全删除 async
/await
,一切都应该按预期工作,或者,您可以使用任务和任务延续重写代码。
我同意 BackgroundWorker
与 async
/await
不兼容的另一个答案。但是,我不同意最简单的解决方案是删除 async
以支持 BackgroundWorker
。 IMO,更好的解决方案(也导致更简单的代码)是删除 BackgroundWorker
以支持 async
;具体来说,replace the outdated BackgroundWorker
with the superior Task.Run
:
// `worker` is now `Task`.
await Task.Run(() => callTestBLE());
finalizeBleTest();
其中 callTestBLE
的签名是 async Task
,而不是 async void
。