【问题标题】:Calling Invoke hangs program调用 Invoke 挂起程序
【发布时间】:2012-12-08 10:19:22
【问题描述】:

基本上,这就是发生的事情。我有一个线程(无限循环),在显示表单时作为后台进程运行。该线程检查是否需要添加新的 ToolStripMenuItem。

如果满足条件,我需要使用 Invoke 来创建 UI 对象,对吗?问题是,当调用 this.Invoke 或 BeginInvoke 时,表单变得无响应,而执行检查的线程仍然运行良好。有什么想法吗?

这是我第一次尝试使用这个多线程的东西。我确定我错过了一些东西。

 public void ThreadSetCom()
    {
        while (true)
        {
            string[] tmpStrPort = System.IO.Ports.SerialPort.GetPortNames();
            IEnumerable<string> diff = tmpStrPort.Except(strPort);
            strPort = tmpStrPort;
            System.Console.WriteLine(System.IO.Ports.SerialPort.GetPortNames().Length);
            foreach (string p in diff)
            {
                var cpDropdown = (ToolStripMenuItem)msMenu.Items["connectToolStripMenuItem"];
                cpDropdown = (ToolStripMenuItem)cpDropdown.DropDownItems["connectReaderToolStripMenuItem"];

                ToolStripMenuItem tsmi = new ToolStripMenuItem();
                tsmi.Text = p;
                tsmi.Name = p;
                tsmi.Click += new EventHandler(itm_Click);

                if (this.msMenu.InvokeRequired)
                {
                    GUIUpdate d = new GUIUpdate(ThreadSetCom);
                    this.Invoke(d);
                }
                else
                {
                    cpDropdownList.DropDownItems.Add(tsmi);
                }                
            }                
        }
    }

【问题讨论】:

  • 我们需要更多细节——理想情况下是一个简短但完整的程序来演示问题。您调用的代码到底是什么样的?
  • 嗨,乔恩,我正在尝试调用上述方法 ThreadSetCom。委托 GUIUpdate 只会回调它所在的方法。我不确定这是否是更新 UI 的正确方法。我见过很少的样本可以做到这一点,所以我只是在尝试。简而言之,这个方法是在表单构造函数中调用的。就是这样。没什么。但它不起作用。你注意到什么问题了吗?
  • 请说明您是如何启动子线程的。你在某处打电话给Join吗?

标签: c# multithreading invoke begininvoke


【解决方案1】:

您的 ThreadSetCom 方法永远不会退出:

while (true)

...没有returnbreak 语句。这将永远挂起 UI 线程。

目前尚不清楚您要实现什么目标,但您绝对不希望在 UI 线程中像这样循环。我认为您不希望在任何线程中以 紧密 的方式循环,请注意...

【讨论】:

  • 嗨乔恩...感谢您指出明显的错误。我觉得好傻。但实际上我认为调用语句会以某种方式(神奇地)使其工作。这是我第一次使用它,所以我有这个奇怪的期望。到目前为止,我看到的示例以这种方式放置代码,所以我认为它是这样做的方式。但是感谢您的帮助:)
  • @user1885498:我怀疑它们中的许多是否包含无限循环 :) 此外,您已经在该循环中访问 UI...除非您是已经在 UI 线程中。
【解决方案2】:

我认为对您来说更好的方法可能是使用BackgroundWorker。我这么说是因为您在 Windows 窗体应用程序中执行多线程时遇到的情况并不少见。此外,BackgroundWorker 能够正确管理线程切换。让我给你一个带有BackgroundWorker的代码示例。

构建私有类变量

private BackgroundWorker _worker;

添加到 CTOR

public {ctor}()
{
    _worker = new BackgroundWorker();
    _worker.WorkerSupportsCancellation = true;
    _worker.WorkerReportsProgress = true;

    _worker.DoWork += new DoWorkEventHandler(BackgroundThreadWork);
    _worker.ProgressChanged += new ProgressChangedEventHandler(BackgroundThreadProgress);
}

DoWork 处理程序

private void BackgroundThreadWork(object sender, DoWorkEventArgs e)
{
    while (!_worker.CancellationPending)
    {
        string[] tmpStrPort = System.IO.Ports.SerialPort.GetPortNames();
        IEnumerable<string> diff = tmpStrPort.Except(strPort);
        strPort = tmpStrPort;
        System.Console.WriteLine(System.IO.Ports.SerialPort.GetPortNames().Length);
        foreach (string p in diff)
        {
            _worker.ReportProgress(1, p);
        }                
    }
}

报告进度处理程序

private void BackgroundThreadProgress(object sender, ReportProgressEventArgs e)
{
    var cpDropdown = (ToolStripMenuItem)msMenu.Items["connectToolStripMenuItem"];
    cpDropdown = (ToolStripMenuItem)cpDropdown.DropDownItems["connectReaderToolStripMenuItem"];

    ToolStripMenuItem tsmi = new ToolStripMenuItem();
    tsmi.Text = e.UserState as string;
    tsmi.Name = e.UserState as string;
    tsmi.Click += new EventHandler(itm_Click);

    cpDropdownList.DropDownItems.Add(tsmi);
}

循环

但是,您必须做的一件事是弄清楚如何摆脱这个循环。什么时候应该退出?无论这意味着什么,您都需要添加到我的示例中存在的 if 语句中,否则这个循环将永远不会结束。

【讨论】:

    【解决方案3】:

    这段代码sn-p的效果是什么:

    GUIUpdate d = new GUIUpdate(ThreadSetCom);
    this.Invoke(d);
    

    是在 UI 线程中调用方法 'ThreadSetCom'。该方法中有一个不定式循环。这就是为什么您的表单变得无响应的原因。

    我建议你应该将foreach 子句移到一个单独的方法中,并在满足条件时在 UI 线程中调用该方法,例如 diff.Count>0。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-19
      • 1970-01-01
      • 1970-01-01
      • 2019-11-24
      相关资源
      最近更新 更多