簡體   English   中英

如何在沒有“函數求值要求所有線程都運行”的情況下在后台調用方法

[英]How can I call a method in the background without “The function evaluation requires all threads to run”

因此,我在一家餐館的Windows窗體應用程序中擁有一個表選擇模塊,該表將至少由4個服務員使用。

在設置表時需要Sync軟件,這很有意義。 我的方法稱為RefreshApp ,至少可以滿足我的需要,就像一個魅力一樣。 問題在於只能在此處成功調用它:

  private void loadTables() { // Some load tables code... RefreshApp(); } 

將方法放到這里,它將完美運行,只需1次...這就是我的問題,我需要不時刷新一下,因此我在BackGroundWorker中嘗試過:

  private void bgWorker_DoWork(object sender, DoWorkEventArgs e) { while (true) { Thread.Sleep(100); if (_stopwatch.Elapsed >= TimeSpan.FromSeconds(Constants.refreshTime) && Constants.alreadyWorking == false) { Constants.alreadyWorking = true; RefreshApp(); // Restart the stopwatch for next sync event _stopwatch.Restart(); } } 

但是,如果我在其中運行代碼,則會得到“函數評估需要運行所有線程”,並且如果我在Button_click方法中使用該代碼以手動形式對其進行測試,則會產生相同的錯誤。

 private void btn_Refresh_Click(object sender, EventArgs e) { RefreshApp(); } 

所以我的問題是,如何在后台的一定時間內調用RefreshApp方法而不會出現此類錯誤?

這是供參考的代碼(請記住,此方法已根據需要工作):

 private void RefreshApp() { SqlDataReader reader = sqlCommandGetTables.ExecuteReader(); // foreach PictureBox representation of a table, get db value, compare, assign table state foreach (PictureBox item in from d in group_Layout.Controls.OfType<PictureBox>().Reverse() select d) { if (item.Name == "DMPS_Layout") continue; reader.Read(); //if the item.Text property equals database value [mesa1], assign image if (item.Text == reader.GetSqlValue(1).ToString() && Int32.Parse(reader.GetValue(0).ToString()) == Constants.numMesaEmpty) item.Image = Properties.Resources.mesaEmpty; if (item.Text == reader.GetSqlValue(1).ToString() && Int32.Parse(reader.GetValue(0).ToString()) == Constants.numMesaBusy) item.Image = Properties.Resources.mesaBusy; if (item.Text == reader.GetSqlValue(1).ToString() && Int32.Parse(reader.GetValue(0).ToString()) == Constants.numMesaUnavailable) item.Image = Properties.Resources.mesaUnavailable; } } 

我不理解該錯誤,但您不應從不同於主線程的其他線程(抽出消息)訪問WinForms控件。 您可以使用Timer(獲取WM_TIMER消息后將在主線程中調用事件)。

您根本無法從BackgroundWorker(在除main之外的任何線程上)調用RefreshApp。

注意:我指的是System.Windows.Forms.Timer (不是System.Threading.Timer
注意2:使用Control.Invoke()(InvokeRequired,BeginInvoke,EndInvoke)是另一個選擇,但是當我用StopWatch看到代碼時,Timer是理想的選擇。

從技術上講,這不是concurrency的情況,因為您只是將代碼從主線程移到了另一個線程。 為了使其工作,您應該在主線程上調用RefreshApp方法:

this.Invoke(RefreshApp);  // `this` being your Form

我認為您在這里得到的錯誤是無關緊要的,但是如果您也想解決該錯誤:您是否在一個喙上設置了條件? 那就是問題所在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM