C#Backgroundworker和Twincat,如何在工作线程内触发通知事件
我对混合事件和线程知之甚少。这种情况是,有一个C#程序运行在PC上,Twincat运行在PLC上。我们需要访问C#程序内部的PLC变量(已经在没有后台工作线程的情况下完成,并且工作正常),现在我们需要将这些处理移动到线程(最好是后台工作线程)。这是不起作用的代码。(该表单包含一个启动按钮,用于启动BGworker,一个停止按钮,用于取消BGworker,以及一个更新按钮,用于将值从PLC更新到文本框。),但现在没有调用tcClient_OnNotification!请指出我缺少的地方,任何帮助都将不胜感激C#Backgroundworker和Twincat,如何在工作线程内触发通知事件,c#,events,backgroundworker,twincat,C#,Events,Backgroundworker,Twincat,我对混合事件和线程知之甚少。这种情况是,有一个C#程序运行在PC上,Twincat运行在PLC上。我们需要访问C#程序内部的PLC变量(已经在没有后台工作线程的情况下完成,并且工作正常),现在我们需要将这些处理移动到线程(最好是后台工作线程)。这是不起作用的代码。(该表单包含一个启动按钮,用于启动BGworker,一个停止按钮,用于取消BGworker,以及一个更新按钮,用于将值从PLC更新到文本框。),但现在没有调用tcClient_OnNotification!请指出我缺少的地方,任何帮助都
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;
}
}
}
提前谢谢。
Abhilash.我猜
TcAdsClient
自己在线程上收到通知,请尝试使用标准消息循环在创建它的线程上调用您的事件
问题是您在ThreadPool
线程上创建了它,并且您没有在那里汇集任何消息,因此您的方法永远不会被调用
你的
BackgroundWorker
看起来完全没用,因为不管怎么说,它没有任何作用。只需删除它。检查TcAdsClient.Synchronize
说:
如果Synchronize设置为true,则通知将同步到
主线。这对于Windows窗体项目是必需的。在里面
控制台应用程序此属性应设置为false
您应该明确检查以下各项是否适用于您:
myTcAdsClient.Synchronize = false
在初始化TcAdsClient实例后立即执行此操作。在严重依赖主线程的基于GUI的应用程序中,将Synchronize设置为true最有意义
在我当前的项目中,我围绕TcAdsClient创建了一个包装器类,以便能够在启动和停止TwinCat环境的Windows服务中使用它,但是包装器设备类将AdsClient托管在一个单独的线程上(在一个无限的Run()循环中)
对于TwinCat变量方面的更改通知,我的包装器类提供了一个自己的事件,Windows服务连接到该事件;每当底层TwinCat客户端的AdsNotificationExEventHandler在设备包装器类中被激发时,就会触发它。当我在WindowsForms应用程序中测试此设置时,一切正常。但不是在控制台应用程序中,也不是在我的Windows服务中-AdsNotificationExEventHandler从未启动过。关键是TcAdsClient的线程同步功能-默认设置是尝试将所有通知同步到主线程上,这对于我的设置来说不是正确的选择。您似乎也是如此。实际上,BackgroundWorker将完成所有数据库工作,这里没有包括我。所以我不能删除它。我不明白你的第二点,你能详细说明一下吗?太糟糕了,op从来没有给出答案,因为这肯定是我今天发现的答案