繁体   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