C # Backgroundworker and Twincat, How to fire a notification event inside a workflow

I did not know about the mixing of events and flows. The scenario is that the PC has a C # and Twincat program running on the PLC. We need to access the PLC variables inside the C # program (already done without the background workflow and its operability). Now we need to transfer this processing to the stream (preferably a background worker). Here is the code that does not work. (The form contains a START button that starts BGworker, a STOP button that cancels BGWorker, and an UPDATE button that updates the values ​​from the PLC to the text box.) But now tcClient_OnNotification is not called! Please indicate where I went missing, any help would be 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; } } } 

Thank you in advance. Abhilash.

+4
source share
3 answers

Check out TcAdsClient.Synchronize

TwinCAT ADS.NET Help says:

If the Sync option is set to true, notifications are synchronized to the Main stream. This is required for Windows Forms projects. In the Console Application, this property must be set to false.

+7
source

Be sure to check if the following works for you:

 myTcAdsClient.Synchronize = false 

Do this immediately after initializing the TcAdsClient instance. Setting Synchronize to true makes sense in GUI-based applications that are heavily dependent on the main thread.

In my current project, I created a wrapper class around TcAdsClient to be able to use it in a Windows service that starts and stops the TwinCat environment, but the wrapper device class places the AdsClient in a separate thread (in an endless run ()).

To notify me of a change in terms of TwinCat variables, my wrapper class offers its own event that the Windows service connects to; it starts whenever the TwinCat base client AdsNotificationExEventHandler starts inside the device shell class. When I tested this setting in a WindowsForms application, everything worked fine. But not in the console application, nor in my Windows service - AdsNotificationExEventHandler never started. The key is a thread synchronization function for TcAdsClient - by default, an attempt is made to synchronize all notifications in the main thread, which was not the right choice for my setup. It seems the same is true for you.

+5
source

I assume that TcAdsClient itself is notified of the thread, try to call your event in the thread that created it using the standard message loop.

The problem is that you created it in the ThreadPool thread, and you do not merge any message there so your method will never be called.

Your BackgroundWorker seems completely useless, as in any case it does not do any work. Just delete it.

0
source

Source: https://habr.com/ru/post/1379601/


All Articles