【问题标题】:How to perform background task without blocking the GUI but transfer back information to main thread?如何在不阻塞 GUI 的情况下执行后台任务但将信息传回主线程?
【发布时间】:2015-04-01 13:13:19
【问题描述】:

我想做以下事情:

  • 在 GUI 上有一个按钮和一个表格。
  • 当我按下按钮时,任务开始
  • 此任务是一个 while 循环,为我提供每次迭代的数据

如何在不阻塞 GUI 的情况下运行此循环并从主 GUI 表中的每次迭代中获取数据?这很重要,因为 while 停止条件又是 GUI 上的一个按钮。

我尝试过使用BackgroundWorker,但我真的不知道如何在每次循环迭代时发回数据(???)我可以在最后取回结果,但这不是目标。如果我在循环中启动工作程序(但工作程序中没有循环),它将不起作用。

private void ContinuousCoordinateAquisition(object sender, DoWorkEventArgs e)
{
    while (continuousPositionAquisitionFlag == true)                       //  while the monitoring is not stopped, get positions
    {
        // get xyzwpr world coordinates
        robotCoordinatesXYZWPRworld XYZWPRworld = robi.getRobotPosition_xyzwpr_world();

        Do something........... retuns values I need in GUI

        // sleep for defined time
        System.Threading.Thread.Sleep(1000); //  wait 
    } 
}

调用将是

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(ContinuousCoordinateAquisition); 
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ContinuousCoordinateAquisitionCompleted);

continuousPositionAquisitionFlag 是从一个按钮(停止按钮)设置的。 ContinuousCoordinateAquisitionCompleted 不幸的是,这里只执行一次,而不是每次迭代。

【问题讨论】:

  • Reactive Extensions 是你的朋友
  • Bgw有一个ProgressChanged事件,非常适合向主线程提交数据。
  • 但是当您在每个循环中暂停 1000 毫秒时,您可能会更好地使用计时器。
  • 你能举个简短的例子吗?我尝试睡眠,但它冻结了 GUI,所以我永远不会到达停止按钮 --> 无限循环.....

标签: c# multithreading backgroundworker


【解决方案1】:

你在正确的轨道上。您应该使用后台工作程序,但不要等待 RunWorkerCompletedEventHandler,这会在一切完成后发生。

相反,在您的循环内定期调用后台工作人员的 ReportProgress 方法。这将触发您可以在 GUI 线程中处理的 ProgressChanged 事件。

请看这里:https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged(v=vs.110).aspx

【讨论】:

  • 好的,所以我添加了: bw.ProgressChanged += new ProgressChangedEventHandler(ContinuousCoordinateAquisitionStep);和 private void ContinuousCoordinateAquisitionStep(object sender, ProgressChangedEventArgs e) { e.???我怎样才能得到这些值? e 这里没有 Result 字段.....
  • 在启动 worker 之前,您需要将 WorkerReportsProgress 属性设置为 True,msdn.microsoft.com/en-us/library/…。在您的“做某事”中,您应该使用包含您希望传输的数据的参数(这是一个用户状态参数,即一个对象)手动调用 ReportProgress 方法。这将触发您的 ProgressChanged 事件。 “e”也将包含您的对象。见这里:msdn.microsoft.com/en-us/library/a3zbdb1t(v=vs.110).aspx
  • 谢谢你,这就是工作:)
【解决方案2】:

尝试设置 BackgroundWorkClass WorkerReportsProgress 属性并处理 ProgressChanged 事件,如本文所述: https://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

【讨论】:

    猜你喜欢
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    相关资源
    最近更新 更多