Iconics Simulator OPC Serve and C# - c#

I'm developing a C# Application for OPC Access via "OPC DA Automation Wrapper 2.02"
For testing on my WIN8 machine I'm using "Iconics Simulator OPC Server 3.12"
I have 4 boolean OPCItems with different names configured on the server.
Connecting, reading the OPCItems works fine.
But:
If I write to ONE of them, the monitor (OPC DataSpy 9.01) and other tools are showing that ALL OPCItems have changed. The Change Event appears for all OPCItems
To check this behaviour, I've written the same application with VisualBasic 6 - same result!
What is wrong, my code or the Simulator Server?
using System;
using System.Windows.Forms;
using OPCAutomation;
namespace opc {
public partial class Form1 : Form {
OPCGroups opcGroups;
OPCGroup opcGroup;
bool aliveToggle;
Timer aliveTimer;
public Form1() {
InitializeComponent();
OPCServer opcServer = new OPCServer();
opcServer.Connect("Iconics.SimulatorOPCDA.2");
opcGroup = opcServer.OPCGroups.Add("Gruppe1");
opcGroup.OPCItems.AddItem("BOOL_1", 1);
opcGroup.OPCItems.AddItem("BOOL_2", 2);
opcGroup.OPCItems.AddItem("BOOL_3", 3);
opcGroup.OPCItems.AddItem("BOOL_4", 4);
opcGroup.UpdateRate = 10;
opcGroup.IsActive = true;
opcGroup.IsSubscribed = true;
aliveTimer = new Timer();
aliveTimer.Tick += new EventHandler(sendAlive);
aliveTimer.Interval=1000;
aliveTimer.Start();
}
private void sendAlive(object sender, EventArgs e) {
aliveToggle=!aliveToggle;
opcGroup.OPCItems.Item(2).Write(aliveToggle);
}
}
}

Easy fix is whenever adding a tag that needs to be event notified independently it should have it's own group, because unfortunately change events are fired on a group basis instead of a tag basis.

Related

C# my application starts in task manager but not shown in Desktop

I created a windows service with Top Shelf. This service tests the battery level and when battery successfully charged(80%) it opens any UI Windows Form or application to nodify me about that (In this example it opens .txt). When i test it in Visual Studio in works perfectly so my UI or any application apperas both in Task Manager and Desktop but when i install it as service, UI or any application appears only in Task Manger not in Desktop here is code:
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
namespace SimpleHeartBeatService
{
public class Heartbeat
{
private readonly System.Timers.Timer _timer; //referance yaratdiq
private static bool firstChecker = true;
private static bool secondChecker = true;
public Heartbeat()
{
_timer = new System.Timers.Timer(1000) //referanca objecr menimsetdik
{
AutoReset = true //Object initializer (kitabda Constr deeper de en axirda var)
};
_timer.Elapsed += TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{ //Bize lazim olan hisse burdan asagidadir
PowerStatus status = SystemInformation.PowerStatus;
if (status.PowerLineStatus.ToString() == "Online" && secondChecker)
{
firstChecker = true;
secondChecker = false;
}
if (firstChecker && status.PowerLineStatus.ToString() == "Online" &&
status.BatteryLifePercent * 100 > 80)
{
Process.Start(#"C:\Users\qarib\Desktop\Test\batteryLevel.txt");
firstChecker = false;
}
if (status.PowerLineStatus.ToString() == "Offline")
{
secondChecker = true;
}
// code here
Thread.Sleep(500);
}
public void Start() //Bunlar mutleq yazilmalidir
{
_timer.Start();
}
public void Stop() //Bunlar mutleq yazilmalidir
{
_timer.Stop();
}
}
}
http://securityinternals.blogspot.com/2014/02/windows-session-0-isolation.html
You can read the details in the article, but suffice it to say that Windows services cannot interact with the desktop of regular users anymore. My guess is that your form is actually opening in Session 0, which is not something you'll normally be able to view or interact with.
In order to get around this problem, here's what my project has done.
We have created a Windows service that exposes some mechanism for communicating with it. In our case, the Windows service originally exposed a WCF-based interface using both sockets and pipes. Because of the overhead, we eventually moved to a TCP socket over localhost, and today we are using shared memory. The mechanism doesn't really matter for the purpose of this discussion. Your service just has to provide some way for a user-run application to connect, communicate, and disconnect.
Once this is in place, you can build an application that provides a UI for communicating with the service. We've done this and allowed the application to be minimized to the system tray to give the appearance that it's a behind-the-scenes thing. The system tray icon then provides a popup menu that allows the user to send commands directly to the service or open the application for additional features.
HTH

Windows Forms graph freezes when the title bar is clicked

I created a Windows Forms application (C#, .NET Framework 4.5) that graphs the data received via the serial line (ex. a sensor attached to a microcontroller). For the graphing I am using ZedGraph library. The problem I ran into is that if I click on the titlebar when the data is being received and plotted, the graph freezes for the duration of the click. As soon as I release the left mouse button, it normally continues the plotting, except that it now just connects the data point received right before the click with the one received right after the mouse button was released. An example is shown below:
This seems to happen only with the graphing part, since the program also outputs the received data to a file. If I plot the received data in another program after the measurement (Excel, Matlab, ...), all the data is as it should be, without any interruptions.
I tried to find what the reason might be, but I could not find a similar example anywhere, so any help would be appreciated.
In order to simplify the process of finding the solution I have also created a smaller program that simply prints the time from the stopwatch to a textBox. Here is the code:
namespace ClickFreezeTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
System.Threading.Thread t = new System.Threading.Thread(() => updateTextBox());
t.IsBackground = true;
t.Start();
}
private void updateTextBox()
{
Stopwatch myStopWatch = new Stopwatch();
myStopWatch.Start();
int a = 1;
while (a == 1)
{
textBox1.BeginInvoke(new Action(() => { textBox1.Text = Convert.ToString(myStopWatch.Elapsed); }));
Thread.Sleep(100);
}
}
}
}
The form looks like this:
As shown in the code above, the textBox is updated every 100 ms on a separate thread. The same problem appears as with the serial graphing program, so I am assuming that if the solution exists it has to do something with the form settings, maybe a control that allows the user to do something with the mouse.

Directx window will not load when debugged

I'm trying to create a window and initializing a device to the window but every time I run the program the window does not load. I am doing this in visual studio 2015 for a windows forms application.
here the form1.cs:
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
namespace DirectXTutorial2
{
public partial class Form1 : Form
{
private Device device;
public Form1()
{
InitializeComponent();
InitializeDevice();
}
public void InitializeDevice()
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
}
private void Render()
{
device.Clear(ClearFlags.Target, Color.DarkSlateBlue, 0, 1);
device.Present();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Render();
}
}
}
Does anyone know of a solution to this?
I don't know if it helps but I am running windows 10, 64 bit, Directx 2010, and I have been added my references before.
okay, i have found a solution to my problem. DirectX for managed code is no longer supported by the devs. the latest framework that works for DirectX is .net Framework 3.5. managed code also does not support 64 bit. to fix this problem go to project properties. in the application tab find target framework and change your .net framework to 3.5 or less. next go to the build tab and find platform target, change this to x86.
First think use try catch in your application, because there is alot of stuff happening in DirectX, so you need to confirm the step, where you are getting error.
try
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed=true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing, presentParams);
}
catch (DirectXException)
{
return false;
}
Try to use different device type like DeviceType.Software.
After clearing your device add begin and end scene
device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0);
device.BeginScene();
device.EndScene();
device.Present();
And try calling your 'Render; function in 'Main' function

How to automate task of consuming webservice

I have a winform application which needs to consume a web service. Web service checks in the database for any changes. If there are any changes in the database the winform application should be notified and will perform some tasks accordingly. How do I do that?
I thought of using timer in my winform application and after say every 5 min connect to a web service and check if new changes are been done in Database. Is there any other way for this?
Update:
I am posting the code here base on the answers:
class PerformTasks
{
public static bool checkIfInProgress { get; set; }
public static void InitializeWebService()
{
try
{
Timer = new System.Timers.Timer(2000);
Timer.Elapsed += OnTimedEvent;
Timer.Enabled = true;
}
}
private static void callService()
{
using (var service = new WebServiceSoapClient())
{
checkIfInProgress = true;
task1();
task2();
popMessage();
checkIfInProgress = false;
}
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
if (checkIfInProgress == false)
{
callService();
}
}
private static void PpopMessage()
{
var form = new Form
{
StartPosition = FormStartPosition.Manual,
ShowInTaskbar = false,
Text = "Message",
Size = new Size(500, 200),
};
var screen = Screen.FromPoint(form.Location);
Label lblText = new Label();
lblText.Text ="Test Text";
lblText.Dock = DockStyle.Fill;
lblText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
form.MaximizeBox = false;
form.Controls.Add(lblText);
form.Location = new Point(screen.WorkingArea.Right - form.Width, screen.WorkingArea.Bottom - form.Height);
form.Show();
}
Now everything works fine except 1 task i.e popMessage(code snippet on top). Here the form is opened but it appears to be loading always. Before using times it used to work fine. How can I handle it?
That's the only way especially if the web service is not WCF-based or if you can't afford to modify it.
If you're using a timer just make sure you use System.Timers.Timer and follow the instructions here so that the Elapsed handler is executed on the UI thread. Moreover, when the timer ticks you should probably spawn a worker thread (or Task, or await on an async method) that makes the service call. You don't want your UI to be blocked while the service call is in progress.
If you have control over the web service, then you may want to explore WCF Duplex Services, which allow you to callback clients from within services.
SignalR allows you to implement Web Services to do this very thing, in real time (no need for a timer or delay between updates). It allows you to set up a persistent connection between client and server, the server is then able to send messages to the client at any point using a stack of transports; WebSockets, Server Sent Events, Forever Frame and Long Polling) based on support available in that order.
You could use SignalR to establish the connection and when something happens on the Server (such as the change in the database you mentioned) broadcast to all clients that need to be notified. eg.
Clients.All.notifyDatabaseChanged(args);

Wrapping an asynchronous method synchronously in C#

I have a third party library containing a class which performs a function asynchronously. The class inherits from the Form. The function basically performs a calculation based on data stored in a database. Once it has finished, it calls a _Complete event in the calling form.
What I would like to do is call the function synchronously but from a non-windows form application. The problem is, no matter what I do, my application blocks and the _Complete event handler never fires. From a windows form I can simulate the function running synchronously by using a "complete" flag and a "while (!complete) application.doevents", but obviously application.doevents isnt available in a non-windows form application.
Is there something that would stop me using the class's method outside of a windows form application (due to it inheriting from 'Form') ?
Is there some way I can work around this ?
Thanks,
Mike
At a stab it might be worth trying something like the following which uses a WaitHandle to block the current thread rather than spinning and checking a flag.
using System;
using System.Threading;
class Program
{
AutoResetEvent _autoEvent;
static void Main()
{
Program p = new Program();
p.RunWidget();
}
public Program()
{
_autoEvent = new AutoResetEvent(false);
}
public void RunWidget()
{
ThirdParty widget = new ThirdParty();
widget.Completed += new EventHandler(this.Widget_Completed);
widget.DoWork();
// Waits for signal that work is done
_autoEvent.WaitOne();
}
// Assumes that some kind of args are passed by the event
public void Widget_Completed(object sender, EventArgs e)
{
_autoEvent.Set();
}
}
I've got some more information on this problem (I'm working in the same team as mikecamimo).
The problem also occurs in the Windows Forms application, when replicated correctly. In the original OP, the problem didn't occur in the windows form because there was no blocking. When blocking is introduced by using a ResetEvent, the same problem occurs.
This is because the event handler (Widget_Completed) is on the same thread as the method calling Widget.DoWork. The result that AutoResetEvent.WaitOne(); blocks forever because the event handler is never called to Set the event.
In a windows forms environment this can worked around by using Application.DoEvents to poll the message queue and allow the event the be handled. See below.
using System;
using System.Threading;
using System.Windows.Forms;
class Program
{
EventArgs data;
static void Main()
{
Program p = new Program();
p.RunWidget();
}
public Program()
{
_autoEvent = new AutoResetEvent(false);
}
public void RunWidget()
{
ThirdParty widget = new ThirdParty();
widget.Completed += new EventHandler(this.Widget_Completed);
data = null;
widget.DoWork();
while (data == null);
Application.DoEvents();
// do stuff with the results of DoWork that are contained in EventArgs.
}
// Assumes that some kind of args are passed by the event
public void Widget_Completed(object sender, EventArgs e)
{
data = e;
}
}
In a non windows forms application, such as a Windows Service, Application is not available so DoEvents cannot be called.
The problem is one of threading and that widget.DoWork's associated event handler somehow needs to be on another thread. This should prevent AutoResetEvent.WaitOne from blocking indefinitely. I think... :)
Any ideas on how to accomplish this would be fantastic.
AutoResetEvent _autoEvent = new AutoResetEvent(false);
public WebBrowser SyncronNavigation(string url)
{
WebBrowser wb = null;
wb = new WebBrowser();
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
wb.ScriptErrorsSuppressed = true;
wb.Navigate(new Uri(url));
while (!_autoEvent.WaitOne(100))
Application.DoEvents();
return wb;
}
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//throw new NotImplementedException();
_autoEvent.Set();
}
Do you have the source for the component? It sounds like it's relying on the fact it will be called from a WinForms environment (must be a good reason why a library inherits from Form!), but it's hard to know for sure.

Categories