【问题标题】:Opening a new thread to do work within GUI class在 GUI 类中打开一个新线程来完成工作
【发布时间】:2013-01-29 06:25:27
【问题描述】:

我在如何解决以下问题时遇到问题。

我有一个类,它允许我在表单上动态更新和显示图表。为了更新图表的值,我在表单的类中有一个方法。我传入值以使用此方法更新图形。这是我正在尝试做的一个高级示例:

类 GUICLass : 表单 {

//绘制图表等的代码都在这里

public updategraphWithNewValue(double value){

 // Code to update the graph

}

}

我的另一堂课如下:

类 ValueProviderForGraph{

GUIClass graphForm = new GUIClass();

公共calculateValuesAndPlot(){

for(int i = 0; i

  graphForm.updategraphWithNewValue(i);

  graphForm.update();

}

}

}

现在我从上面得到的问题是表单在此操作发生时冻结。我该如何解决这个问题,任何帮助或建议将不胜感激。我希望这个高级示例有足够的信息,如果没有,请告诉我,我会尝试更好地解释自己。 谢谢。

【问题讨论】:

    标签: c# multithreading forms


    【解决方案1】:

    考虑使用BackgroundWorker。它面向事件的界面应该能让您快速启动并运行。

    【讨论】:

    • BackgroundWorker 使用过时的异步编程模型。虽然它非常适合简单的案例,但我宁愿花时间学习 TPL。
    【解决方案2】:

    您只能从最初创建控件的线程更新表单的控件。

    如果您尝试从不同的线程更新它,您必须编组该调用。网上有很多方法。我个人最喜欢的(对于 WinForms)如下:

    https://stackoverflow.com/a/709846/141172

    更新

    在@StenPetrov 的敦促下重新阅读您的问题后,我怀疑您毕竟没有跨线程问题,但 UI 线程在更新图形时根本没有处理消息(这会导致操作过程中的冻结)。

    如果 UI 线程忙于更新图表,您将获得该行为。但是,看起来您正在导致图表进行 3999 次不必要的更新。尝试移动线路

    graphForm.update();
    

    在你的 for 循环之外。

    虽然我不确切知道您的图形控件是如何工作的,但我怀疑对 update() 的调用会导致重新渲染整个图形。只有在添加了所有新数据点之后,您才应该这样做。

    【讨论】:

    • 无关紧要。如果线程是一个问题,它会抛出一个异常
    • @StenPetrov:正是在这种情况下,我经历了 UI 冻结。也许某个异常被抛出并被捕获(包括在全局异常处理程序中)。
    • 读取 OP -“在操作时冻结...”,而不是“挂起”或“崩溃”
    • 嘿,谢谢您的回复 :) 在添加点之后将更新移动到将摆脱图形的动态状态,因此我将看不到图形,并且在所有迭代之后添加了所有点。这可能是我的错,因为我的问题的细节非常有限。上面的 for 循环是我实际在做的事情的简化版本,它是在我的神经网络中训练和计算错误。然后我将此错误绘制到图表中。
    【解决方案3】:

    您是否需要经常更新 UI?

    如果您不必经常更新 UI,例如加载大图进行查看,那么 BackgroundWorker 就可以了。

    如果您需要频繁更新 UI,您必须 (a) 使图形计算独立于 UI,(b) 在单独的线程中运行图形计算,以及 (c) 在计算更新后使用 Form.Invoke(. ..) 更新用户界面

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-18
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多