我有一个问题跟随,非常简化的案例是我的项目的一部分 . 考虑我们有如下GUI:
我有两个背景工作者:
plot_bgworker - 在这个例子中,它增加了绘图计数器,
data_bgworker - 在此示例中,它递增数据计数器 .
我还有label_timer,它会更新我的表单上显示的递增值 .
为了管理后台工作者和计时器,我写了两个函数:
private: void turnOnAcquisition() {
if (!counting_paused)
return;
if (!plot_bgworker->IsBusy)
plot_bgworker->RunWorkerAsync();
if (!data_bgworker->IsBusy)
data_bgworker->RunWorkerAsync();
label_timer->Enabled = true;
counting_paused = false;
}
private: void turnOffAcquisition() {
if (counting_paused)
return;
if (plot_bgworker->IsBusy)
plot_bgworker->CancelAsync();
if (data_bgworker->IsBusy)
data_bgworker->CancelAsync();
label_timer->Enabled = false;
counting_paused = true;
}
然后,当我点击每个按钮时会发生以下情况:
// Pauses counting on click
private: System::Void stop_btn_Click(System::Object^ sender, System::EventArgs^ e) {
turnOffAcquisition();
}
// Starts counting on click
private: System::Void start_btn_Click(System::Object^ sender, System::EventArgs^ e) {
turnOnAcquisition();
}
// Should restart counting on click, beginning from 0 (no matter what state counting is in right now)
private: System::Void restart_btn_Click(System::Object^ sender, System::EventArgs^ e) {
plot_counter = 0;
data_counter = 0;
turnOffAcquisition();
turnOnAcquisition();
}
最后,这里是我的后台工作人员(由CancelAsync()/ RunWorkerAsync()关闭/打开)和计时器:
// Calculating data counter
private: System::Void data_bgworker_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
for (;;) {
data_counter++;
Sleep(50);
if (data_bgworker->CancellationPending) {
e->Cancel = true;
return;
}
}
}
// Calculating plot counter
private: System::Void plot_bgworker_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
for (;;) {
plot_counter++;
Sleep(120);
if (plot_bgworker->CancellationPending) {
e->Cancel = true;
return;
}
}
}
// Display counters
private: System::Void label_timer_Tick(System::Object^ sender, System::EventArgs^ e) {
plot_counter_label->Text = numToMStr(plot_counter);
data_counter_label->Text = numToMStr(data_counter);
}
开始按钮和停止按钮都按预期工作,但现在我遇到重启按钮的问题 . 当我在计数过程中单击它时,它似乎重置值并停止后台工作者,但从不再启动它们(正如我在调用turnOnAcquisition后所期望的那样) . 但是,当我在计数关闭时单击它时,我可以按预期开启计数 .
我的第一个镜头是,当我试图检查我的工作人员是否忙时,取消标志还没有设置为另一个值,但是在呼叫之间使用Sleep()不起作用 . 另一个猜测是,它是由于竞争条件失败,所以我尝试使用MemoryBarrier(),但我不知道库,我不确定它是否会起作用 . 此外,我尝试使用Interlocked类,但无法正确使用它来处理void函数 .
1. Is this way of thinking correct? 2. If yes, why simple Sleep() doesn't do the trick? 3. How would I use any of mentioned methods in this case and which one would be the best match?