c#想要多个ui线程,但却得到交叉引用错误

时间:2013-05-25 19:07:45

标签: multithreading user-interface begininvoke cross-reference

我仍然非常擅长c#,线程和表单。我正在写一个小型的数据采集程序。它有两个线程:主ui线程和传感器轮询/日志记录/图表线程。当用户单击“开始记录”按钮时,它会连续轮询传感器(通过虚拟COM端口),将响应写入文件,使用一些基本轮询统计(每秒多少轮询)更新主表单。如果用户单击了“监视器”按钮,它将打开一个图表表单,轮询线程将调用一个方法,将传感器值添加到图表中。

我有一个非常好的程序版本,但我发现如果我打开多个图表(这样我可以实时查看多个传感器),图表更新会变得零星或停止,只有焦点的窗口顺利更新。 (通信端口只有56kbaud,因此不像投票被数据所淹没。)

所以我得到了制作图表线程的“明智”想法,认为这会提供多个UI循环,并会在多个图表表单上生成漂亮的平滑图表。以下是简化代码;例如此处,图表线程是使用轮询线程启动的,而不是在用户单击“监视器”按钮时启动。它编译,但是当它运行时,我在调用update_chart方法时得到一个交叉引用错误。

似乎我对线程和控制所有权的几个方面有一个基本的误解。图表是在“图表”线程中创建的,但是当“轮询”线程调用update_chart方法时,代码显示update_chart方法由“main_ui”线程运行。我愿意接受任何建议/建议,我会给你顺利的图表和统计数据更新。感谢。

namespace WindowsFormsApplication1
{
    public partial class Main_Form : Form
    {
        delegate void UpdateUIStatsDelegate(string update);
        UpdateUIStatsDelegate update_stats_delegate;

        static BackgroundWorker polling_thread = new BackgroundWorker();
        static BackgroundWorker charting_thread = new BackgroundWorker();

        public static Chart_Form chart_form = new Chart_Form();

        public Main_Form()
        {
            Thread.CurrentThread.Name = "main_ui";

            update_stats_delegate = new UpdateUIStatsDelegate(update_stats);

            polling_thread.DoWork += polling_thread_DoWork;
            charting_thread.DoWork += charting_thread_start;
        }

        private void start_logging_Click(object sender, EventArgs e)
        {
            start_polling_thread();
            start_charting_thread();
        }

        private void start_polling_thread()
        {
            polling_thread.RunWorkerAsync();
        }

        private void polling_thread_DoWork(object sender, DoWorkEventArgs e)
        {
            string sensor_values;

            Thread.CurrentThread.Name = "polling";

            while (true)
            {
                sensor_values = poll_the_sensors_and_collect_the_responses();
                log_to_file(sensor_values);

                // BeginInvoke(chart_form.update_chart_delegate, new object[] { sensor_values });
                chart_form.BeginInvoke(chart_form.update_chart_delegate, new object[] { sensor_values });

                pps = compute_polling_performance();
                BeginInvoke(update_stats_delegate, new object[] { pps.ToString("00") });
            }
        }

        private void update_stats(string stat)
        {
            string tn = Thread.CurrentThread.Name;
            // this says "main_ui", but i don't get a cross-reference error

            pollings_per_second.Text = stat;
        }

        private void start_charting_thread()
        {
            charting_thread.RunWorkerAsync();
        }

        private void charting_thread_start(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.Name = "charting";
            Chart_Form chart_form = new Chart_Form();
            chart_form.Show();
            while (charting_is_active) { }
        }
    }

    public partial class Chart_Form : Form
    {
        public delegate void UpdateChartDelegate(string sensor_values);
        public UpdateChartDelegate update_chart_delegate;

        public Chart_Form()
        {
            string tn = Thread.CurrentThread.Name;
            update_chart_delegate = new UpdateChartDelegate(update_chart);
            this.Text = "a realtime plot of sensor values";
        }

        private void update_chart(string sensor_values)
        {
            string tn = Thread.CurrentThread.Name;
            // this says "main_ui" and i get a cross reference error; set below.

            int x = extract_x_value(sensor_values);
            int y = extract_y_value(sensor_values);

            chart1.Series[X_AXIS].Points.AddY(x);  // <<--- i get a cross-reference runtime error here...
            chart1.Series[Y_AXIS].Points.AddY(y);
        }
    }
}

0 个答案:

没有答案