简体   繁体   中英

Populate DataGridView from thread

I am writing code in Microsoft Visual C# 2010 Express for a USB2-F-7x02 CANBus adapter that transmits messages via USB from a TEKTRONIX 020-2924-XX DPO DEMO 2 Board.

The code below called CANSnifferForm.cs uses a GUI that interacts with the CANBus API. The Run_Click will open the adapter (canplus_open) after the user clicks "Run" before the adapter starts listening (canplus_Listen). The callback thread (setReceiveCallBackThread) then runs which calls setReceiveCallBack that calls callback. The msg object contains the message. My problem then lies in getting this information from the message and adding it to the DataGridView (dataGridView1).

I have considered many possibilities.

The most obvious one was simply adding rows to the dataGridView by writing "this.dataGridView1.Rows.Add(msg.id, msg.len, msg.timestamp);" in callback. However, callback is in fact static but dataGridView1 isn't. Unfortunately, I CANNOT remove the static keyword since it would result in syntax errors with the calling functions. Also, I cannot declare dataGridView1 as static since this would result in syntax errors with initialization in the design forms file.

A second option was to open a file and write to it. However, when I declared and used a StreamWriter object, errors concerning callback being statically declared resulted. So then I decided to output to the console and redirect it to a file using trace (since Console.WriteLine isn't static). I found a discussion on trace here:

Trace .

However, the program would have to parse through this file and output it to the dataGridView right after the thread started. This would mean that as the thread wrote to the file, the StreamReader object would read from it simulataneously possibly resulting in data complications. This was causing the program to not respond when I ran it.

So then I finally considered declaring a static array and populating it in callback. There were problems with initializing the array. However, in order to parse it with a loop and place it into the dataGridView, I would have to know how big the array is to start with. The size changes as I use a loop to parse through it.

I am starting to loose patience with this. So I am presenting my question to stack overflow.

The three following pieces of code should contain everything necessary to analyze the problem. The EASYSYNC.msg is declared in EASYSYNC.cs. The primary coding that I am doing is in CANSnifferForm.cs.

// CANSnifferForm.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;

namespace WindowsFormsApplication1
{

    public partial class CANSnifferForm : Form
    {

        // per the api document. "This is a blocking call and must be called on a separate thread."
        // the code previously after setCallback... was never being reached because the call is   blocking.
        // this calls the setCallbackThread function in another thread so processing can continue.
        Thread setReceiveCallBackThread;
        //static int arrSize = 0;

        int handle, listenReturnValue;
        TextWriter tw = new StreamWriter("dataGridView1.txt");

        public CANSnifferForm()
        {
            InitializeComponent();
        }


        private static void callback(ref EASYSYNC.CANMsg msg)
        {
            // Populate something perhaps??
        }

        EASYSYNC.CallbackDelegate del = new EASYSYNC.CallbackDelegate(callback);

        private void Run_Click(object sender, EventArgs e)
        {

            this.CANSnifferStatusBox.AppendText("CAN closed");
            this.ProcessStatusBox.AppendText("Stopped");
            EASYSYNC.CANMsg msg = new EASYSYNC.CANMsg();
            msg.id = 1;
            msg.timestamp = 2;
            msg.flags = 3;
            msg.len = 4;
            msg.data = 5;
            handle = EASYSYNC.canplus_Open(IntPtr.Zero, "1000", IntPtr.Zero, IntPtr.Zero, 0);

            if (handle < 0)
                this.ErrorBox.AppendText("Error opening CAN");

            this.CANSnifferStatusBox.Clear();
            this.CANSnifferStatusBox.AppendText("CAN open");


            setReceiveCallBackThread = new Thread(() => EASYSYNC.canplus_setReceiveCallBack(handle, callback));
            listenReturnValue = EASYSYNC.canplus_Listen(handle);

            if (listenReturnValue < 0)
            {
                this.ErrorBox.Clear();
                this.ErrorBox.AppendText("Error setting listen mode\n");
                EASYSYNC.canplus_Close(listenReturnValue);
                this.CANSnifferStatusBox.Clear();
                this.CANSnifferStatusBox.AppendText("CAN closed\n");
            }

            this.CANSnifferStatusBox.Clear();
            this.CANSnifferStatusBox.AppendText("CAN Listening\n");

            setReceiveCallBackThread.Start();
            this.ProcessStatusBox.Clear();
            this.ProcessStatusBox.AppendText("Running\n");

            // Insert loop here to populate dataGridView
            // this.dataGridView1.Rows.Add(msg.id, msg.len, msg.timestamp);



        }

      private void Stop_Click(object sender, EventArgs e)
        {
           setReceiveCallBackThread.Abort(); // Stop thread
           this.ProcessStatusBox.Clear();
           this.ProcessStatusBox.AppendText("Stopped");
           EASYSYNC.canplus_Close(listenReturnValue);
           this.CANSnifferStatusBox.Clear();
           this.CANSnifferStatusBox.AppendText("CAN closed");

        }
}


// CANSnifferProgram.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    static class CANSnifferProgram
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new CANSnifferForm());


        }
    }
}

// EASYSYNC.cs

using System;
using System.Runtime.InteropServices;
using System.Text;


internal class EASYSYNC
{
    public const string CAN_BitRate_100K = "100";
    public const string CAN_BitRate_10K = "10";
    public const string CAN_BitRate_125K = "125";
    public const string CAN_BitRate_1M = "1000";
    public const string CAN_BitRate_20K = "20";
    public const string CAN_BitRate_250K = "250";
    public const string CAN_BitRate_500K = "500";
    public const string CAN_BitRate_50K = "50";
    public const string CAN_BitRate_800K = "800";
    public const byte CANMSG_EXTENDED = 0x80;
    public const byte CANMSG_RTR = 0x40;
    public const uint canplus_ACCEPTANCE_CODE_ALL = 0;
    public const uint canplus_ACCEPTANCE_MASK_ALL = uint.MaxValue;
    public const byte CANPLUS_FLAG_BLOCK = 4;
    public const byte CANPLUS_FLAG_NO_LOCAL_SEND = 0x10;
    public const byte CANPLUS_FLAG_QUEUE_REPLACE = 2;
    public const byte CANPLUS_FLAG_SLOW = 8;
    public const byte CANPLUS_FLAG_TIMESTAMP = 1;
    public const byte CANSTATUS_EWARN = 1;
    public const byte CANSTATUS_RXB0OVFL = 0x80;
    public const byte CANSTATUS_RXB1OVFL = 0x40;
    public const byte CANSTATUS_RXBP = 8;
    public const byte CANSTATUS_RXWARN = 2;
    public const byte CANSTATUS_TXBO = 0x20;
    public const byte CANSTATUS_TXBP = 0x10;
    public const byte CANSTATUS_TXWARN = 4;
    public const int ERROR_CANPLUS_COMMAND_SUBSYSTEM = -3;
    public const int ERROR_CANPLUS_FAIL = -1;
    public const int ERROR_CANPLUS_INVALID_HARDWARE = -11;
    public const int ERROR_CANPLUS_INVALID_PARAM = -6;
    public const int ERROR_CANPLUS_MEMORY_ERROR = -8;
    public const int ERROR_CANPLUS_NO_DEVICE = -9;
    public const int ERROR_CANPLUS_NO_MESSAGE = -7;
    public const int ERROR_CANPLUS_NOT_OPEN = -4;
    public const int ERROR_CANPLUS_OK = 1;
    public const int ERROR_CANPLUS_OPEN_SUBSYSTEM = -2;
    public const int ERROR_CANPLUS_TIMEOUT = -10;
    public const int ERROR_CANPLUS_TX_FIFO_FULL = -5;
    public const uint FLUSH_DONTWAIT = 1;
    public const uint FLUSH_EMPTY_INQUEUE = 2;
    public const uint FLUSH_WAIT = 0;

    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Close(int handle);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Flush(int h);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_getFirstAdapter(StringBuilder szAdapter, int size);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_getNextAdapter(StringBuilder szAdapter, int size);
    [DllImport("USBCanPlusDllF.dll", EntryPoint="canplus_VersionInfo")]
    public static extern int canplus_getVersionInfo(int handle, StringBuilder verinfo);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Listen(int handle);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Open(IntPtr szID, string szBitrate, IntPtr acceptance_code, IntPtr acceptance_mask, uint flags);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Open(string szID, string szBitrate, IntPtr acceptance_code, IntPtr acceptance_mask, uint flags);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Open(string szID, string szBitrate, string acceptance_code, string acceptance_mask, uint flags);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Read(int handle, ref CANMsg msg);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_ReadN(int handle, ref CANMsg msg);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Reset(int handle);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_SetTimeouts(int handle, uint receiveTimeout, uint transmitTimeout);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Status(int handle);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_Write(int handle, ref CANMsg msg);
    [DllImport("USBCanPlusDllF.dll")]
    public static extern int canplus_setReceiveCallBack(int handle, CallbackDelegate callback);

    [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
    public delegate void CallbackDelegate(ref CANMsg msg);

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct CANMsg
    {
        public uint id;
        public uint timestamp;
        public byte flags;
        public byte len;
        public ulong data;
    }

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct CANMsgEx
    {
        public uint id;
        public uint timestamp;
        public byte flags;
        public byte len;
    }
}


// CANSnifferForm.Designer.cs
namespace WindowsFormsApplication1
{
    partial class CANSnifferForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.RunRestart = new System.Windows.Forms.Button();
            this.Stop = new System.Windows.Forms.Button();
            this.Pause = new System.Windows.Forms.Button();
            this.Resume = new System.Windows.Forms.Button();
            this.FilterLength = new System.Windows.Forms.TextBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.FilterByID = new System.Windows.Forms.Label();
            this.FilterbyLength = new System.Windows.Forms.Label();
            this.CANSnifferStatus = new System.Windows.Forms.Label();
            this.ErrorBox = new System.Windows.Forms.TextBox();
            this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.ID = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.Length = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.Data = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.TimeStamp = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.ErrorMessage = new System.Windows.Forms.Label();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.ProcessStatus = new System.Windows.Forms.Label();
            this.ProcessStatusBox = new System.Windows.Forms.TextBox();
            this.CANSnifferStatusBox = new System.Windows.Forms.TextBox();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // RunRestart
            // 
            this.RunRestart.Location = new System.Drawing.Point(56, 80);
            this.RunRestart.Margin = new System.Windows.Forms.Padding(4);
            this.RunRestart.Name = "RunRestart";
            this.RunRestart.Size = new System.Drawing.Size(125, 39);
            this.RunRestart.TabIndex = 0;
            this.RunRestart.Text = "Run / Restart";
            this.RunRestart.UseVisualStyleBackColor = true;
            this.RunRestart.Click += new System.EventHandler(this.Run_Click);
            // 
            // Stop
            // 
            this.Stop.Location = new System.Drawing.Point(1009, 80);
            this.Stop.Name = "Stop";
            this.Stop.Size = new System.Drawing.Size(154, 39);
            this.Stop.TabIndex = 12;
            this.Stop.Text = "Stop";
            this.Stop.UseVisualStyleBackColor = true;
            this.Stop.Click += new System.EventHandler(this.Stop_Click);
            // 
            // Pause
            // 
            this.Pause.Location = new System.Drawing.Point(232, 80);
            this.Pause.Name = "Pause";
            this.Pause.Size = new System.Drawing.Size(120, 39);
            this.Pause.TabIndex = 13;
            this.Pause.Text = "Pause";
            this.Pause.UseVisualStyleBackColor = true;
            this.Pause.Click += new System.EventHandler(this.Pause_Click);
            // 
            // Resume
            // 
            this.Resume.Location = new System.Drawing.Point(411, 80);
            this.Resume.Name = "Resume";
            this.Resume.Size = new System.Drawing.Size(122, 39);
            this.Resume.TabIndex = 14;
            this.Resume.Text = "Resume";
            this.Resume.UseVisualStyleBackColor = true;
            this.Resume.Click += new System.EventHandler(this.Resume_Click);
            // 
            // FilterLength
            // 
            this.FilterLength.Location = new System.Drawing.Point(620, 88);
            this.FilterLength.Name = "FilterLength";
            this.FilterLength.Size = new System.Drawing.Size(161, 22);
            this.FilterLength.TabIndex = 16;
            this.FilterLength.TextChanged += new System.EventHandler(this.FilterLength_TextChanged);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(850, 88);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(57, 22);
            this.textBox1.TabIndex = 17;
            // 
            // FilterByID
            // 
            this.FilterByID.AutoSize = true;
            this.FilterByID.Location = new System.Drawing.Point(617, 63);
            this.FilterByID.Name = "FilterByID";
            this.FilterByID.Size = new System.Drawing.Size(75, 17);
            this.FilterByID.TabIndex = 18;
            this.FilterByID.Text = "Filter by ID";
            this.FilterByID.Click += new System.EventHandler(this.FilterByID_Click);
            // 
            // FilterbyLength
            // 
            this.FilterbyLength.AutoSize = true;
            this.FilterbyLength.Location = new System.Drawing.Point(847, 63);
            this.FilterbyLength.Name = "FilterbyLength";
            this.FilterbyLength.Size = new System.Drawing.Size(106, 17);
            this.FilterbyLength.TabIndex = 19;
            this.FilterbyLength.Text = "Filter by Length";
            this.FilterbyLength.Click += new System.EventHandler(this.FilterbyLength_Click);
            // 
            // CANSnifferStatus
            // 
            this.CANSnifferStatus.AutoSize = true;
            this.CANSnifferStatus.Location = new System.Drawing.Point(53, 9);
            this.CANSnifferStatus.Name = "CANSnifferStatus";
            this.CANSnifferStatus.Size = new System.Drawing.Size(121, 17);
            this.CANSnifferStatus.TabIndex = 21;
            this.CANSnifferStatus.Text = "CANSniffer Status";
            this.CANSnifferStatus.Click += new System.EventHandler(this.CANSnifferStatus_Click);
            // 
            // ErrorBox
            // 
            this.ErrorBox.BackColor = System.Drawing.SystemColors.Control;
            this.ErrorBox.Location = new System.Drawing.Point(180, 35);
            this.ErrorBox.Name = "ErrorBox";
            this.ErrorBox.Size = new System.Drawing.Size(220, 22);
            this.ErrorBox.TabIndex = 22;
            // 
            // dataGridViewTextBoxColumn1
            // 
            this.dataGridViewTextBoxColumn1.DataPropertyName = "Target";
            this.dataGridViewTextBoxColumn1.HeaderText = "Target";
            this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
            this.dataGridViewTextBoxColumn1.ReadOnly = true;
            // 
            // dataGridView1
            // 
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
            this.ID,
            this.Length,
            this.Data,
            this.TimeStamp});
            this.dataGridView1.Location = new System.Drawing.Point(17, 156);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.RowTemplate.Height = 24;
            this.dataGridView1.Size = new System.Drawing.Size(1146, 388);
            this.dataGridView1.TabIndex = 23;
            this.dataGridView1.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellContentClick);
            // 
            // ID
            // 
            this.ID.HeaderText = "ID";
            this.ID.Name = "ID";
            this.ID.Width = 200;
            // 
            // Length
            // 
            this.Length.HeaderText = "Length";
            this.Length.Name = "Length";
            // 
            // Data
            // 
            this.Data.HeaderText = "Data";
            this.Data.Name = "Data";
            this.Data.Width = 600;
            // 
            // TimeStamp
            // 
            this.TimeStamp.HeaderText = "Time Stamp";
            this.TimeStamp.Name = "TimeStamp";
            this.TimeStamp.Width = 200;
            // 
            // ErrorMessage
            // 
            this.ErrorMessage.AutoSize = true;
            this.ErrorMessage.Location = new System.Drawing.Point(53, 35);
            this.ErrorMessage.Name = "ErrorMessage";
            this.ErrorMessage.Size = new System.Drawing.Size(101, 17);
            this.ErrorMessage.TabIndex = 24;
            this.ErrorMessage.Text = "Error Message";
            // 
            // progressBar1
            // 
            this.progressBar1.Location = new System.Drawing.Point(17, 133);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(69, 17);
            this.progressBar1.TabIndex = 26;
            // 
            // ProcessStatus
            // 
            this.ProcessStatus.AutoSize = true;
            this.ProcessStatus.Location = new System.Drawing.Point(617, 12);
            this.ProcessStatus.Name = "ProcessStatus";
            this.ProcessStatus.Size = new System.Drawing.Size(103, 17);
            this.ProcessStatus.TabIndex = 28;
            this.ProcessStatus.Text = "Process Status";
            // 
            // ProcessStatusBox
            // 
            this.ProcessStatusBox.BackColor = System.Drawing.SystemColors.Menu;
            this.ProcessStatusBox.Location = new System.Drawing.Point(726, 12);
            this.ProcessStatusBox.Name = "ProcessStatusBox";
            this.ProcessStatusBox.Size = new System.Drawing.Size(148, 22);
            this.ProcessStatusBox.TabIndex = 29;
            this.ProcessStatusBox.TextChanged += new System.EventHandler(this.ProcessStatusBox_TextChanged);
            // 
            // CANSnifferStatusBox
            // 
            this.CANSnifferStatusBox.BackColor = System.Drawing.SystemColors.Menu;
            this.CANSnifferStatusBox.Location = new System.Drawing.Point(180, 6);
            this.CANSnifferStatusBox.Name = "CANSnifferStatusBox";
            this.CANSnifferStatusBox.Size = new System.Drawing.Size(163, 22);
            this.CANSnifferStatusBox.TabIndex = 31;
            this.CANSnifferStatusBox.TextChanged += new System.EventHandler(this.textBox2_TextChanged);
            // 
            // CANSnifferForm
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1357, 533);
            this.Controls.Add(this.CANSnifferStatusBox);
            this.Controls.Add(this.ProcessStatusBox);
            this.Controls.Add(this.ProcessStatus);
            this.Controls.Add(this.progressBar1);
            this.Controls.Add(this.ErrorMessage);
            this.Controls.Add(this.dataGridView1);
            this.Controls.Add(this.ErrorBox);
            this.Controls.Add(this.CANSnifferStatus);
            this.Controls.Add(this.FilterbyLength);
            this.Controls.Add(this.FilterByID);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.FilterLength);
            this.Controls.Add(this.Resume);
            this.Controls.Add(this.Pause);
            this.Controls.Add(this.Stop);
            this.Controls.Add(this.RunRestart);
            this.Margin = new System.Windows.Forms.Padding(4);
            this.Name = "CANSnifferForm";
            this.Text = "CAN Sniffer ";
            this.Load += new System.EventHandler(this.Form1_Load);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button RunRestart;
        private System.Windows.Forms.Button Stop;
        private System.Windows.Forms.Button Pause;
        private System.Windows.Forms.Button Resume;
        private System.Windows.Forms.TextBox FilterLength;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Label FilterByID;
        private System.Windows.Forms.Label FilterbyLength;
        private System.Windows.Forms.Label CANSnifferStatus;
        private System.Windows.Forms.TextBox ErrorBox;
        private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.DataGridViewTextBoxColumn ID;
        private System.Windows.Forms.DataGridViewTextBoxColumn Length;
        private System.Windows.Forms.DataGridViewTextBoxColumn Data;
        private System.Windows.Forms.DataGridViewTextBoxColumn TimeStamp;
        private System.Windows.Forms.Label ErrorMessage;
        private System.Windows.Forms.ProgressBar progressBar1;
        private System.Windows.Forms.Label ProcessStatus;
        private System.Windows.Forms.TextBox ProcessStatusBox;
        private System.Windows.Forms.TextBox CANSnifferStatusBox;
    }
}

You can in fact, make your callback method non-static. The delegate takes care of being marshalled with a thunk to make a "this call". The trick is that you cannot initialize that delegate outside of the Form's constructor. The reason is that outside of the ctor, there is no "this". Declare it like so:

private EASYSYNC.CallbackDelegate del;

Then initialize it in your constructor:

del = new EASYSYNC.CallbackDelegate(callback);

Make sure you pass "del" , not "callback" when you call EASYSYNC.canplus_setReceiveCallBack (you currently have it wrong). It is desirable to retain a reference to this delegate as it gets passed to unmanaged code. When you passed "callback", a delegate was created, but you didn't get the opportunity to hold on to the reference, and we're going to re-use that reference inside of callback.

The tricky bit is in the callback method. You cannot add an item to the DGV (or even to a bound container) from another thread. UI controls cannot be accessed from a thread other than the UI thread they were created on. We can simply check to see if we are executing on another thread, and if so we will use BeginInvoke to re-invoke ourselves, this time from the UI thread.

private void callback(ref EASYSYNC.CANMsg msg)
{
    if (InvokeRequired)
        BeginInvoke(del, msg);
    else
    {
        // Now you can add items to the DGV
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM