2

基本上,这就是发生的事情。我有一个线程(无限循环),在显示表单时作为后台进程运行。该线程检查是否需要添加新的 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);
                }                
            }                
        }
    }
4

3 回答 3

2

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

while (true)

...没有returnbreak声明。这将永远挂起 UI 线程。

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

于 2012-12-08T10:51:55.043 回答
0

我认为对您来说更好的方法可能是使用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语句,因为否则此循环将永远不会结束。

于 2012-12-08T11:04:24.633 回答
0

这段代码片段的效果是什么:

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

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

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

于 2012-12-08T11:12:03.887 回答