如何从不同的线程调用方法

时间:2018-04-27 18:11:35

标签: c#

我试图使用多线程同时绘制两个图形,但是,图表会返回一条错误消息,指出" 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);
    }

任何帮助都将不胜感激。

2 个答案:

答案 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()的主线程。如果它已经在主线程上,我们只是进行更改。

另外,请参阅以下资源:

https://www.dotnetperls.com/async

https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls

答案 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));