基本上,这就是发生的事情。我有一个线程(无限循环),在表单显示时作为后台进程运行。线程检查是否需要添加新的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);
}
}
}
}
答案 0 :(得分:2)
您的ThreadSetCom
方法永不退出:
while (true)
...没有return
或break
语句。这将永远挂起UI线程。
目前尚不清楚你想要实现的目标,但你绝对不希望像在UI线程中那样循环。我认为你不想在任何线程中以紧的方式循环,请注意......
答案 1 :(得分:0)
我认为更好的方法可能是使用BackgroundWorker
。我这样说是因为在Windows窗体应用程序中进行多线程处理时遇到的情况并不少见。此外,BackgroundWorker
能够正确地管理线程切换。让我举一个带有BackgroundWorker
的代码示例。
private BackgroundWorker _worker;
public {ctor}()
{
_worker = new BackgroundWorker();
_worker.WorkerSupportsCancellation = true;
_worker.WorkerReportsProgress = true;
_worker.DoWork += new DoWorkEventHandler(BackgroundThreadWork);
_worker.ProgressChanged += new ProgressChangedEventHandler(BackgroundThreadProgress);
}
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 语句,因为此循环永远不会以其他方式结束。
答案 2 :(得分:0)
此代码段的效果如何:
GUIUpdate d = new GUIUpdate(ThreadSetCom);
this.Invoke(d);
是将在UI线程中调用'ThreadSetCom'方法。并且该方法中存在不定式循环。这就是为什么你的表单没有反应。
我建议您将foreach
子句移动到单独的方法,并在命中条件时在UI线程中调用此方法,例如diff.Count&gt; 0.