我遇到以下問題,非常簡化的情況是我的項目的一部分。考慮到我們有GUI象下面這樣:Windows窗體:後臺工作人員同步和管理
我有兩個背景工人:
- 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);
}
開始埠tton和停止按鈕都按預期工作,但現在我遇到了重啓按鈕的問題。當我在計數過程中單擊它時,它似乎重置值並停止後臺工作,但從不再次啓動它們(正如我在調用turnOnAcquisition之後所期望的那樣)。但是,當計數關閉時單擊它時,我可以按預期開啓計數。
我的第一個鏡頭是當我試圖檢查我的工作人員是否忙碌時,取消標記尚未設置爲另一個值,但在通話之間使用Sleep()並不起作用。另一個猜測是,它是由於競爭條件失敗,所以我嘗試使用MemoryBarrier(),但我不知道這些庫,我不知道它是否會工作。另外,我嘗試使用Interlocked類,但無法正確使用它作爲void函數。
1.這種思維方式是否正確?
2.如果是的話,爲什麼簡單的睡眠()不會做的伎倆?
3.在這種情況下,我將如何使用上述方法中的哪一種,哪一種方法最適合?