Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Backgroundworker and Twincat, How to fire Notification event inside worker thread

I had little knowledge about mixing events and threads. The scenario is that there is a C# program running on a PC and Twincat running on a PLC. We need to access PLC variables inside the C# program ( Already done without a background worker thread and its working fine.) , Now we need to move these processing to a thread ( preferably Background Worker ). Here is the code which is not working.( The form contains a START button , which will start BGworker, a STOP button which will cancel BGWorker, and an UPDATE button which will update the values from PLC to a textbox.), But now tcClient_OnNotification is not getting called! Please point out where i am missing, any help will be most appreciated.

    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;         // not added by default
    using System.IO;                // not added by default
    using TwinCAT.Ads;              // not added by default

    namespace BGworker
    {
        public partial class Form1 : Form
        {
            private BackgroundWorker bw = new BackgroundWorker();
            private TcAdsClient tcClient;   // C# program is the client.
            private AdsStream dataStream;   // Data transfered through System IOStream
            private BinaryReader binReader; // We are now reading value from PLC
            private int Hintval;            // Handle for integer value

            public static bool looping = true;
            public static string receivedtext = "";

            public Form1()
            {
                InitializeComponent();

                bw.WorkerReportsProgress = true;
                bw.WorkerSupportsCancellation = true;
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            }

            private void Form1_Load(object sender, EventArgs e)
            {

            }


            private void Startbutton_Click(object sender, EventArgs e)
            {
                if (bw.IsBusy != true)
                {
                    bw.RunWorkerAsync();
                }

            }




            private void Stopbutton_Click(object sender, EventArgs e)
            {
                if (bw.WorkerSupportsCancellation == true)
                {
                    bw.CancelAsync();
                }
            }


            public void bw_DoWork(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
                dataStream = new AdsStream(1 * 2); // Single value will be read
                binReader = new BinaryReader(dataStream, Encoding.ASCII);
                tcClient = new TcAdsClient();
                tcClient.Connect(801);
                //Hintval = tcClient.CreateVariableHandle(".GOUTINT");
                Hintval = tcClient.AddDeviceNotification(".GOUTINT", dataStream, 0, 2, AdsTransMode.OnChange, 100, 0, null);
                tcClient.AdsNotification += new AdsNotificationEventHandler(tcClient_OnNotification);

                while (true)
                {
                    if ((worker.CancellationPending == true))
                    {
                        e.Cancel = true;
                        break;
                    }
                    else
                    {
                        System.Threading.Thread.Sleep(100);
                        //worker.ReportProgress((5* 10));

                    }
                }

                tcClient.Dispose();
            }


            public void tcClient_OnNotification(object sender, AdsNotificationEventArgs e)
            {
                try
                {
                    // Setting the position of e.DataStream to the position of the current required value
                    e.DataStream.Position = e.Offset;

                    // Determining which variable has changed
                    if (e.NotificationHandle == Hintval)
                    {
                        receivedtext = binReader.ReadInt16().ToString();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

            private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if ((e.Cancelled == true))
                {
                    this.tbProgress.Text = "Canceled!";
                }

                else if (!(e.Error == null))
                {
                    this.tbProgress.Text = ("Error: " + e.Error.Message);
                }

                else
                {
                    this.tbProgress.Text = "Done!";
                }
            }
            private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                this.tbProgress.Text = (e.ProgressPercentage.ToString() + "%");
            }

            private void buttonUpdate_Click(object sender, EventArgs e)
            {
                this.tbProgress.Text = receivedtext;
            }

        }
    }

thanks in advance. Abhilash.

like image 261
abhilash Avatar asked Dec 16 '22 07:12

abhilash


1 Answers

Check TcAdsClient.Synchronize

TwinCAT ADS.NET Help says:

If Synchronize is set to true, the notifications are synchronized onto the Main thread. This is necessary for Windows Forms projects. In Console Application this property should be set to false.

like image 175
PhilMY Avatar answered Jan 23 '23 11:01

PhilMY