我的主要表单Form1
正在运行我程序的主要部分。
我有一个单独的线程开始执行算法。
当我从新线程运行方法时,方法MyAlgorithm()
我收到错误
InvalidOperationException,消息“控制控件名称是从创建它的线程以外的线程访问的。”
如何返回原始线程以便运行方法以使用最新值更新文本框?
这是我想要运行的方法,包含在我的应用程序中的主要类Form1中。
// Reset the results values
public void ShowResults()
{
while (true)
{
loopsNum.Text = Convert.ToString(resultLoopsNum);
nodesVisitedNum.Text = Convert.ToString(resultNodesVisitedNum);
nodesResolvedNum.Text = Convert.ToString(resultNodesResolvedNum);
cpuLoopsNum.Text = Convert.ToString(resultCpuLoopsNum);
shortestPathCostNum.Text = Convert.ToString(resultShortestPathCost);
}
}
我查看了Invoke()方法,但我不知道如何从thread方法中获取Form1的原始实例。
我正在调用我的线程......
// Set the algorithm method up in it's own thread
Thread thread = new Thread(new ThreadStart(MyAlgorithm));
// Run the algorithm
thread.Start();
答案 0 :(得分:5)
如何返回原始线程以便运行方法以使用最新值更新文本框?
在Windows窗体中,您使用Control.Invoke
/ BeginInvoke
或使用BackgroundWorker
并执行更新进度事件处理程序。
在WPF中,您使用Dispatcher.Invoke
/ BeginInvoke
。
在C#5和.NET 4.5中,您将能够使用异步方法,这样可以使这很简单......
我查看了Invoke()方法,但我不知道如何从thread方法中获取Form1的原始实例。
如果“线程方法”只是Form
的实例方法,那么您已经获得了this
引用。如果不是,您需要提供该信息 - 理想情况下为ISynchronizeInvoke
,以避免直接依赖Windows窗体,如果您可以单独表达“更新”部分。 (现在这个界面有点被弃用,有利于同步上下文,但它仍然可以很好地运行。)
答案 1 :(得分:2)
public void ShowResults()
{
while (true)
{
Thread.Sleep(1000); // don't spam the UI thread
if (this.InvokeRequired)
{
this.Invoke((Action)UpdateGui);
}
else
{
UpdateGui();
}
}
}
private void UpdateGui()
{
loopsNum.Text = Convert.ToString(resultLoopsNum);
nodesVisitedNum.Text = Convert.ToString(resultNodesVisitedNum);
nodesResolvedNum.Text = Convert.ToString(resultNodesResolvedNum);
cpuLoopsNum.Text = Convert.ToString(resultCpuLoopsNum);
shortestPathCostNum.Text = Convert.ToString(resultShortestPathCost);
}
答案 2 :(得分:1)
您可以使用:
myform.Invoke(ShowResults);
答案 3 :(得分:1)
这里还有其他选择:
或者使用System.Forms.Timer
定期致电ShowResults
。或者另一种选择是不使用另一个线程来进行操作;当您想让GUI更新时,在GUI线程中执行此操作并从操作中调用Application.DoEvents()
。
第一个选项很好,因为它可以防止意外地使用Invoke
个请求充斥GUI,第二个选项很好,因为它全部在GUI线程上,允许您对事物进行精细控制显示在GUI上。