c# wanting multiple ui threads but getting cross-reference errors instead

心已入冬 提交于 2019-12-12 04:58:00

问题


i'm still very new at c#, threads and forms. i'm writing a small data acquistion program. it has two threads: the main ui thread and a sensor polling/logging/charting thread. when the user clicks the "start-logging" button, it it continuously polls the sensors (over a virtual COM port), writes the response to a file, updates the main form with some basic polling stats (how many pollings per second). if the user has clicked a "monitor" button, it opens a charting form and the polling thread invokes a methods that that adds the sensors values to the chart.

i have a version of this program that works very well but i found that if i have multiple charts open (so that i can view multiple sensors in realtime), the chart updates become sporadic or stop and only the window with the focus updates smoothly. (the comm port is only 56kbaud so it's not like the polling is being swamped with data.)

so i got the "bright" idea to make charting threads, thinking this would provide multiple UI loops and would produce nice smooth charting on multiple chart forms. below is simplified code; e.g. here, the charting thread is started with the polling thread instead of when the user clicks the "monitor" button. it compiles, but when it runs, i get a cross-reference error at the point when the update_chart method is called.

seems i have a fundamental misunderstanding of several things about threads and control ownership. the chart was made in the "charting" thread, but when the "polling" thread invokes the update_chart method, the code shows that update_chart methods is being run by the "main_ui" thread. i'm open to any suggestions/advise that'll give me smooth charting and stats updates. thanks.

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);
        }
    }
}

来源:https://stackoverflow.com/questions/16752996/c-sharp-wanting-multiple-ui-threads-but-getting-cross-reference-errors-instead

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!