c# - 在执行期间将信息从 UI 传递到 BackgroundWorker

2024-04-09

我有一个使用后台工作线程的 C# 应用程序,并且非常成功地从正在运行的线程更新 UI。该应用程序涉及网络上的最短路径路由,随着后台工作进程的进行,我在 UI 上显示网络和最短路径。我想允许用户在应用程序运行时通过使用滑块减慢显示速度。

我发现这是一个建议,但它是在 vb.net 中,我不清楚如何让它在 c# 中工作。

BackgroundWorker 在运行时如何从 UI 线程获取值? https://stackoverflow.com/questions/8701243/how-can-the-backgroundworker-get-values-from-the-ui-thread-while-it-is-running

我可以将滑块的值传递给后台工作者,如下所示:

// 启动异步操作。 延迟 = this.trackBar1.Value; backgroundWorker1.RunWorkerAsync(延迟);

并在后台工作线程中使用它,但它只使用最初发送的值。当我在 UI 上移动滑块时,我不清楚如何从后台工作人员内部获取值。

我以前使用过多个线程和委托,但如果可以使用后台工作程序,我会更喜欢它,因为它很简单。

2012年5月10日

感谢大家的回复。我仍然遇到问题,很可能是因为我的结构方式。网络路由的繁重计算是在 TransportDelayModel 类中完成的。 BackgroundWorker_DoWork 创建此类的一个实例,然后启动它。延迟在 TransportDelayModel 中处理。

代码骨架如下:

In UI:

 private void runToolStripMenuItem1_Click(object sender, EventArgs e)
    {
        if (sqliteFileName.Equals("Not Set"))
        {
            MessageBox.Show("Database Name Not Set");
            this.chooseDatabaseToolStripMenuItem_Click(sender, e);

        }

        if (backgroundWorker1.IsBusy != true)
        {
            // Start the asynchronous operation.
            delay = this.trackBar1.Value;
            // pass the initial value of delay
            backgroundWorker1.RunWorkerAsync(delay);
            // preclude multiple runs
            runToolStripMenuItem1.Enabled = false;
            toolStripButton2.Enabled = false;
        }

    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        if (!backgroundWorkerLaunched)
        {
            // instantiate the object that does all the heavy work
            TransportationDelayModel TDM = new TransportationDelayModel(worker, e);               
            // kick it off
            TDM.Run(sqliteFileName, worker, e);
            backgroundWorkerLaunched = true;
        }


    }

TransportDelayModel 构造函数是:

 public TransportationDelayModel(BackgroundWorker worker, DoWorkEventArgs e)
    {
        listCentroids = new List<RoadNode>();
        listCentroidIDs = new List<int>();
        listNodes = new List<RoadNode>();
        listNodeIDs = new List<int>();
        listRoadLink = new List<RoadLink>();
        roadGraph = new AdjacencyGraph<int, RoadLink>(true); // note parallel edges allowed
        tdmWorker = worker;
        tdmEvent = e;
        networkForm = new NetworkForm();
    }

所以我有 tdmWorker,它允许我将信息传递回 UI。

在TransportationDelayModel的内部计算中,我睡眠了延迟时间

  if (delay2 > 0)
                                    {
                                        tdmWorker.ReportProgress(-12, zzz);
                                        System.Threading.Thread.Sleep(delay2);
                                    }

所以问题似乎是如何将更新的滑块值从 UI 传递回后台工作程序中执行的对象。我尝试了多种组合,有点折腾,但无济于事,要么什么也没有发生,要么我收到一条关于不允许访问另一个线程上发生的事情的消息。我意识到,如果我在 DoWork 事件处理程序中完成所有工作,那么我应该能够按照您的建议执行操作,但要实现这一点太复杂了。

再次感谢您的建议和帮助。

6/2/2012

我已经通过两种方法解决了这个问题,但我有一些疑问。根据我对 R. Harvey 的评论,我构建了一个简单的应用程序。它由一个带有运行按钮、滑块和富文本框的表单组成。运行按钮启动一个后台工作线程,该线程实例化一个“模型”类的对象来完成所有工作(我的 TransportModel 的简化代理)。 Model 类只是将 100 行写入文本框,将每行中的点数增加 1,每行之间根据滑块的设置以及行末尾的滑块值设置延迟,类似于这:

...................................58

................................58

......................58

......................................51

........................44

......................44

此练习的目标是能够在“模型”运行时移动表单上的滑块,并获得更改的延迟(如上所示)。

我的第一个解决方案涉及创建一个 Globals 类,以保存滑块的值:

class Globals
{
    public static int globalDelay;
}

然后,在表单中,每当滚动轨迹栏时我都会更新此值:

private void trackBar1_Scroll(object sender, EventArgs e)
    {
        Globals.globalDelay = this.trackBar1.Value;
    } 

在模型中,我只是选取全局的值:

 public void Run(BackgroundWorker worker, DoWorkEventArgs e)
 {

     for (int i = 1; i < 100; i++)
     {
         delay = Globals.globalDelay; // revise delay based on static global set on UI
         System.Threading.Thread.Sleep(delay);
         worker.ReportProgress(i);
         string reportString = ".";
         for (int k = 0; k < i; k++)
         {
             reportString += ".";
         }
         reportString += delay.ToString();
         worker.ReportProgress(-1, reportString);

     }
 }
}

这很好用。 我的问题:这种方法有什么缺点吗?它看起来很容易实现,而且很普遍。

第二种方法基于 R. Harvey 的建议,利用委托和调用。

我为代表创建一个类:

 public class MyDelegates
{
    public delegate int DelegateCheckTrackBarValue(); // create the delegate here
}

在表格中,我创建:

  public int CheckTrackBarValue()
    {
        return this.trackBar1.Value;

    } 

Model 类现在有一个成员 m_CheckTrackBarValue

 public class Model 
{

#region Members

Form1 passedForm;
public static MyDelegates.DelegateCheckTrackBarValue m_CheckTrackBarValue=null;      
#endregion Members

#region Constructor
public Model(BackgroundWorker worker, DoWorkEventArgs e, Form1 form)
{
    passedForm = form;
}

当后台线程通过运行按钮启动时,调用表单被传递

私人无效button1_Click(对象发送者,EventArgs e) { 如果(backgroundWorker1.IsBusy!= true) {

            backgroundWorker1.RunWorkerAsync();

        }
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {

        BackgroundWorker worker = sender as BackgroundWorker;

        if (!backgroundWorkerLaunched)
        {
            // instantiate the object that does all the heavy work
            Model myModel= new Model(worker, e, this);

            Model.m_CheckTrackBarValue = new MyDelegates.DelegateCheckTrackBarValue(this.CheckTrackBarValue);

            // kick it off
            myModel.Run(worker, e);
            backgroundWorkerLaunched = true;
        }
    }

最后,在 Model 中,在传递的表单上调用 Invoke 方法来获取轨迹栏的值。 公共无效运行(BackgroundWorker工人,DoWorkEventArgs e) {

     for (int i = 1; i < 100; i++)
     {
         int delay = (int)passedForm.Invoke(m_CheckTrackBarValue,null); // invoke the method, note need the cast here
         System.Threading.Thread.Sleep(delay);
         worker.ReportProgress(i);
         string reportString = ".";
         for (int k = 0; k < i; k++)
         {
             reportString += ".";
         }
         reportString += delay.ToString();
         worker.ReportProgress(-1, reportString);

     }
 }

这也有效。在将成员变量设置为静态之前,我一直收到错误,例如 公共静态 MyDelegates.DelegateCheckTrackBarValue m_CheckTrackBarValue=null;

我对此解决方案的疑问:与之前的版本相比,该解决方案有优势吗?我的实现方式是否让事情变得太复杂了?为什么 m_CheckTrackBarValue 需要是静态的。

我对这次编辑的长度表示歉意,但我认为其他人可能会对这个问题和解决方案感兴趣。


你必须通过TrackBar反对BackgroundWorker, not delay. delay一旦设置就不会改变。

为了简化所需的Invoke(),您可以使用辅助方法,例如this one http://www.codeproject.com/Articles/29829/Towards-Cleaner-Code-II-a-C-GUI-Invoke-Async-Helpe:

Async.UI(delegate { textBox1.Text = "This is way easier!"; }, textBox1, true);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c# - 在执行期间将信息从 UI 传递到 BackgroundWorker 的相关文章

随机推荐

  • 如何调试特定的 JavaScript 点击事件?

    在雅虎天气页面上 有一个链接标记为C改变温度单位Fahrenheit to Celsius 我正在寻找调试此操作并了解 JavaScript 在幕后执行的内容 将 F 转换为 C 调试此类操作的方法是什么 Link http weather
  • phpMyAdmin 错误 504 网关超时重新加载

    我的 phpmyadmin 有一个非常烦人的问题 它出乎意料地出现 据我所知 我的专用服务器没有发生任何变化 当我尝试在浏览器中执行任何查询或显示执行时间超过 1 秒的视图时 Windows 7 上的 firefox 即行为相同 我收到以下
  • 在类中声明一个数组。 C++

    我想创建一个初始化数组和函数的类push向数组添加一个元素而不是打印它 作为初学者 我知道初始化有问题 除了函数之外一切正常push 它不打印数组 我的班级出了什么问题 include
  • 使用 exiftool 编辑 MP4 元数据

    我有一个 MP4 文件Title元数据 exiftool movie mp4 这使 Audio Bits Per Sample 16 Audio Sample Rate 48000 Handler Type Metadata Handler
  • 获取USB设备的父信息C++

    我正在开发一个 MFC 工具 用于检查连接的 USB 设备的一些驱动程序信息 例如位置信息 父级 硬件 ID 等 我已经获得了我想要的所有其他信息 但我一直在获取设备父级信息 我用过安装程序API dll在我的代码中获取设备信息 使用获取U
  • MSBuild with Azure - PublishProfileSet 计算结果为“”

    我正在尝试将我的项目部署到 Azure 我首先在 Azure 上研究 EF 代码几个小时 但我只用了一次就创建了一个用户 我去发布更新 现在收到以下错误 Invoke build failed due to exception Expect
  • QGraphicsView 和 QGraphicsItem:缩放视图矩形时不缩放项目

    我正在使用 QtQGraphicsView and QGraphicsItem 子类 当视图矩形更改时 有没有办法不缩放视图中项目的图形表示 例如放大时 默认行为是我的项目相对于我的视图矩形进行缩放 我想可视化二维点 这些点应该由一个细矩形
  • 我怎样才能卷曲深度爬行?

    我的 Deepcrawl 爬行仅给出 null 值 ch curl init curl setopt ch CURLOPT URL https api deepcrawl com accounts 00000 projects 195334
  • is.na() 应用于非(列表或向量)类型“NULL”意味着什么?

    我想从没有 NA 的 data frame 中选择具有前向过程的 Cox 模型 这是一些示例数据 test lt data frame x 1 runif 100 0 1 x 2 runif 100 0 5 x 3 runif 100 10
  • 检测 iOS 中的旋转变化

    我正在制作一个 iOS 应用程序 需要在旋转时进行一些界面重新排列 我试图通过实施来检测这一点 void orientationChanged NSNotification note 但这会在设备正面朝上或正面朝下时向我发出通知 我想要一种
  • 如何将数组对象中的数据保存到 MongoDB

    我在将数据从数组对象保存到 MongoDB 数据库时遇到问题 我有带有嵌入子文档的主文档的架构 主文档和所有其他子文档的保存均成功 但子文档是数组除外 正如您从屏幕截图中看到的 子文档中的字段没有保存到数据库中 Robo 3T 的屏幕截图
  • TaskGraph.useFilter 替代 kotlin dsl

    我正在寻找 gradle 中这行代码的替代方案 并且正在寻找 kotlin dsl 中的对应部分 任何人都可以对此进行一些说明 因为它阻止了我的构建 并且由于 usefilter 在 kotlin dsl 中不可用而不知所措 gradle
  • 双击:缩放 Android MapView?

    经过一些工作后 我的路线应用程序运行良好 我唯一想添加的是双击放大功能 但我不知道如何添加 你能给我一个提示吗 我也一直在寻找答案 示例 但找不到有效的代码 最后 这是对我有用的代码 MyMapActivity java public cl
  • 确定一个数字是否是十的倍数或在一组特定范围内

    我的程序中有一些需要的循环 我可以写出伪代码 但我不完全确定如何逻辑地编写它们 I need if num is a multiple of 10 do this if num is within 11 20 31 40 51 60 71
  • MvvmCross 5.x 的 MvvmCross 侧边栏导航

    我要为我的应用程序实现两种类型的导航 即侧边栏导航和父子导航 我的应用程序从汉堡 侧边栏 菜单开始 侧边栏菜单中的第一项应执行导航堆栈的重置并打开主视图 主视图控制器应该启动根堆栈导航 因此主视图上的每个按钮都应该打开一个新视图 新视图上的
  • 运行 Django 应用程序时出错

    当我在 pycharm 或 cmd 中运行 django 项目时 出现此错误 我应该怎么办 C Program Files x86 JetBrains PyCharm 3 4 1 bin runnerw exe C Python34 pyt
  • 如何简化url

    你好 在我的网站中 我发现他们的网址非常简单 例如 http example com questions 4486620 randomaccessfile probelm http example com questions 4486620
  • 为什么 MonkeyRunner.waitForConnection() 在我的环境中不起作用?

    Script from com android monkeyrunner import MonkeyRunner MonkeyDevice device MonkeyRunner waitForConnection 5 192 168 6
  • 在 SQL Server 2008 中存储闰秒

    这个周末是一个特别长的周末 因为将会有一场额外的第二秒 http en wikipedia org wiki Leap second Insertion of leap seconds插入之后23 59 596月30日 我们有一个全天候记录
  • c# - 在执行期间将信息从 UI 传递到 BackgroundWorker

    我有一个使用后台工作线程的 C 应用程序 并且非常成功地从正在运行的线程更新 UI 该应用程序涉及网络上的最短路径路由 随着后台工作进程的进行 我在 UI 上显示网络和最短路径 我想允许用户在应用程序运行时通过使用滑块减慢显示速度 我发现这