我试图使用多线程同时绘制两个图形,但是,图表会返回一条错误消息,指出" Control' chart1'从其创建的线程以外的线程访问。"。我相信这可以使用" Invoke"来解决,但我不确定如何做到这一点。
以下是一个图表和一个帖子的简化代码:
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(thread);
th.Start();
}
public void graph(List<double> xlist, List<double> ylist)
{
chart1.Series["1"].Points.DataBindXY(xlist, ylist);
}
public void thread()
{
List<double> xlist = new List<double>();
List<double> ylist = new List<double>();
//Assume xlist and ylist have a range of numerical elements
graph(xlist, ylist);
}
任何帮助都将不胜感激。
答案 0 :(得分:0)
这是因为在使用Windows Forms时,唯一可以更新GUI的线程是主线程。您可以使用async await
模式解决此问题,以便在后台运行计算,并invoke
更新GUI所需的方法。
以下是一个例子:
private void MyMethod(var myObject)
{
if (form.myControl.InvokeRequired)
{
form.myControl.Invoke((MethodInvoker)delegate {
// Running on the UI thread
form.myControl.MyMethod(myObject);
});
// Back on the worker thread
}
else //Must already be on the UI thread
{
form.myControl.MyMethod(myObject);
}
}
在这个方法中,我们检查代码是否在InvokeRequired
的主线程上运行,如果不是,我们从委托创建MethodInvoker
并运行我们的更改使用control.Invoke()
的主线程。如果它已经在主线程上,我们只是进行更改。
另外,请参阅以下资源:
答案 1 :(得分:0)
这就是它的完成方式:
chart1.Invoke(c => c.Series["1"].Points.DataBindXY(xlist, ylist), new object[] { chart1 });
为了便于在多个地方使用,您可以编写扩展方法:
public static class ControlExtensions
{
public static void UpdateOnUIThread<T>(this T control, Action<T> action) where T : ISynchronizeInvoke
{
if (control.InvokeRequired)
control.Invoke(action, new object[] { control });
else
action(control);
}
}
并将其用作:
chart1.UpdateOnUIThread(c => c.Series["1"].Points.DataBindXY(xlist, ylist));