VB.NET Synchronization confusion - vb.net

VB.NET, .NET 4
Hello all,
I have an application that controls an industrial system. It has a GUI which, once a process is started, principally displays the states of various attached devices. It basically works like this:
A System.Timers.Timer object is always running. At each Elapsed event, it polls the devices for their current values and invokes controls on the GUI, updating them with the new values.
A start button is clicked, a process time Stopwatch object is created and started (Labels on the GUI are now invoked and updated on the System.Timers.Timer's Elapsed event, in addition to the other work that is taken care of on this event)
A new thread is created which runs a Process() subroutine
Some Stopwatch objects are created and started (these Stopwatches are periodically restarted during the process via their Restart() method.
Some logic is executed on the new Stopwatchs' Elapsedmilliseconds properties to determine when to do things like write new setpoints to the devices, update the data log, etc...
Here's my problem: The program occasionally freezes. My ignorant efforts at tracking down the problem have led me to suspect that read/writes to the subset of devices that are RS-232 controlled are the culprits most of the time. However, I occasionally see other strange things upon program freeze, e.g., one of the time Labels whose Text property is determined by a Stopwatch's Elapsedmilliseconds property sometimes will show an impossible value (e.g., -50 hours or something).
For the RS-232 problems, I suspect something like a read event is being executed at the same time as a write event and this causes a freeze(?). I tried to prevent this by making sure that all communication with an RS-232 device is funneled through a Transmit() subroutine which has the following attribute:
Which, as far as my ignorance permits me to understand, should force one Transmit() execution to finish completely before another one can start. Perhaps another risk is the code getting blocked here if one Transmit() never finishes?
Regarding the Stopwatch trouble, I speculate that the problem is that the Timer is trying to update a GUI Label at the same time that the Stopwatch's Restart() method is being executed. I'm unsure if this could cause a problem. All I know is that this problem has only occurred at a point in the process when a Restart() call would be made.
I am wondering if I could use a SyncLock or something to lock a Stopwatch while the Label is being updated (or, conversely, while its being restarted)? Or, perhaps I should stop the Timer, restart the Stopwatch, and then start the timer again, like so?:
Timer.Stop
Stopwatch.Restart
Timer.Start
My trepidation regarding how to proceed is due to my complete lack of understanding of how .NET synchronization objects actually work. I've tried slapping a few SyncLocks in various places, but I really have no idea if they're implemented correctly or not. I'm wondering if, having provided all this context, someone really smart might be able to tell me how I'm stupid and how to do this right. I would really appreciate any input. If it would be useful to provide some code snippets, I'd be happy to, I just worry that everything's so convoluted that it would just detract from what I'm hoping is a conceptual question.
Thanks in advance!
Brian

I would consider a shift to a task scheduling framework instead of relying on manual manipulation of timers if your working on anything SCADA related. A simple starting point would be something similar to the hardcodet.Scheduling classes and you can move to something like the beast that is Quartz. Most of these types of frameworks will provide you with a way to pause and resume scheduled actions.
If I'm working with Modbus, I normally keep a local cache of the register values and make changes to any value fire a change event. This has the benefit of allowing you to implement things like refreshing values manually without interfering with your process scheduling and checking for deadband when evaluating your polled response. This happened to be the side effect of implementing a polled protocol to a subset of the OPC DA interface.

Related

Create a wxPython app that has only one instance

I would like to create a wxPython app such that:
If I run a second instance of that app (e.g., call the Python script from the shell a second time), no new instance should be created.
Instead, the toplevel frame of the already running instance should be raised and focussed.
The first point can be easily implemented by wx.SingleInstanceChecker (see the example code there), but at least the example code only gives a way for making the second instance of the app abort, but not raise the existing app's main frame.
I am using wxPython-Phoenix with Python 3.
Claritication: I would much prefer an out-of-the-box solution like wx.SingleInstanceChecker (that is, not implement my own locking and IPC solution).
You can use any kind of IPC to send a message asking the other program to do whatever needs to be done (just raise its top level window or maybe handle the command line options passed to the second instance). In C++ there are wxConnection and the related wxServer and wxClient classes that can be used for this, but I'm not sure if they're wrapped by wxPython -- however you could use any Python IPC module instead, if they aren't.
As has been pointed out, the "correct" way to do this is IPC because you have a new process that is supposed to affect a change (raise and focus) in another process.
What you seem to want is to take advantage of the IPC channel that wx.SingleInstanceChecker is already using to do your work. Unfortunately, you can't. That class is implemented in the wxWidgets c++ code and therefore there are no Python bindings to the internal workings of the class.
However, you can probably abuse wx.SingleInstanceChecker to do what you want. In your program, you can set up a timer at some rapid interval (say, 250ms) that will constantly check IsAnotherRunning() from your main process. Therefore, when your second process starts up, the first will notice and can raise itself to the front. You would just have to wait for a little bit in the secondary process before it exits, to give the first time to notice.

Labview Program changes behavior after looking at (not changing) the Block Diagram

My Labview Program works like a charm, until I look at the Block Diagram. No changes are made. I do not Save. Just Ctrl+E and then Ctrl+R.
Now it does not work properly. Only a Restart of Labview fixes the problem.
My Program controls two Scanner arrays for Laser Cutting simultaneously. To force parallel working, I use the Error handler and loops that wait for a signal from the Scanner. But suddenly some loops run more often than they should.
What does majorly happen in Labview when I open the Block diagram that messes with my code?
Edit:
Its hard to tell what is happening without violating my non-disclosure agreement.
I'm controlling two independent mirror-Arrays for Laser Cutting. While one is running one Cutting-Job, the other is supposed to run the other Jobs. Just very fast. When the first is finished they meet at the same position and run the same geometry at the same slow speed. The jobs are provided as *.XML and stored as .net Objects. The device only runs the most recent job and overwrites it when getting a new one.
I can check if a job is still running. While this is true I run a while loop for the other jobs. Now this loop runs a few times too often and even ignores WAIT-blocks to a degree. Also it skips the part where it reads the XML job file, changes the speed part back to fast again and saves it. It only runs one time fast.
#Joe: No it does not. It only runs once well. afterwards it does not.
Youtube links
The way it is supposed to move
The wrong way
There is exactly one thing I can think of that changes solely by opening the block diagram.
When the block diagram opens, any commented-out or unreachable-code-compiler-eliminated sections of code will load their subVIs. If one of those commented out sections of code were somehow interfere with your running code, you might have an issue.
There are only two ways I know of for that to interfere... both of them are fairly improbable.
a) You have some sort of "check for all VIs in memory" or "check for all types in memory" that you're using as a plug-in system. When the commented-out sections load, that would change the VIs in memory. Such systems are not uncommon when parsing XML, so maybe.
b) You are using Run VI method for some dynamically invoked VI to execute as a top-level VI, but by loading the diagram, it discovers that it is a subVI of your current program. A VI cannot simultaneously be top-level and a subVI, so the call to Run VI returns an error.
That's it. I can't think of anything else. Both ideas seem unlikely, but given your claim and a lack of a block diagram, I figured I'd post it as a hypothesis.
In the improbable case someone has a similar problem. The problem was a xml file that was read during run time. Sometimes multiple instances tried to access it and this produced the error.
Quick point to check: are Debug and "retain data in wires" disabled? While it may not change the computations, but it may certainly change the timing of very tight loops, and that was one of the unexpected program behaviors, OP was referring to.

VB .net Infinite Loop/Interrupt Driven

I'm pretty new to VB .net still and I'm attempting to write a program that constantly watches information pulled from a PLC and updates when it changes.
I've worked some with microcontrollers and I know making an infinite loop works well. What I'm running into with my VB .net code is when it loops, the form basically freezes up and the label never updates. I attempted using the code below.
Do While True
*Code*
Loop
So, I guess my first question is, what is the best way to go about having a continuous program to update data. It seems an infinite loop is not the answer.
My second question is, like microcontrollers, is it possible to have VB .net be an interrupt driven program instead of an event driven. My program is always running, updating the data as it comes in, but if a button is pressed it can essentialy break out of the loop. Or what I have in mind, temporarly leave the loop to perform another function then continue back into the loop.
I've looked at the System.Timers namespace, and am not 100% clear on how they work. It seems like it is potential answer to my problem. If I have a timer that does the code every one second, this one second occures as long as the form is running correct? Assuming the previous statement is correct, if the code is running from the 1 second tick, and a button is pushed while that code is running, will the button be ignored, or will the event happen after the code has finished.
Anything to help me learn will be greatly appeciated!
You can use the
Application.DoEvents()
-method provided by the .NET framework, it essentially updates your form to apply all the changes that happened in the meantime.

What is the 'COM context' referred to in the 'ContextSwitchDeadlock' MDA message?

While running unit tests, I'm getting the MDA shown below.
In the error message, what is the hexadecimal value refered to as a 'COM context'?
Can I determine this value for a given STA thread? If so, how?
Managed Debugging Assistant
'ContextSwitchDeadlock' has detected a
problem in 'C:\Program Files\Microsoft
Visual Studio
9.0\Common7\IDE\vstesthost.exe'. Additional Information: The CLR has
been unable to transition from COM
context 0x14cff0 to COM context
0x14d218 for 60 seconds. The thread
that owns the destination
context/apartment is most likely
either doing a non pumping wait or
processing a very long running
operation without pumping Windows
messages. This situation generally has
a negative performance impact and may
even lead to the application becoming
non responsive or memory usage
accumulating continually over time. To
avoid this problem, all single
threaded apartment (STA) threads
should use pumping wait primitives
(such as CoWaitForMultipleHandles) and
routinely pump messages during long
running operations.
From what I can see (looking at mscorwks disassembly) it is a IObjContext*, returned from CoGetContextToken().
Basically it looks like a call is queued up using IContextCallback::ContextCallback() from mscorwks!CtxEntry::EnterContextOle32BugAware(), which in turn calls mscorwks!CtxEntry::EnterContextCallback() once the object context (apartment) processes the message. They use a CLREvent to signal callback completion. For STA threads, not pumping messages would cause the event wait to timeout, which triggers the ContextSwitchDeadlock MDA.
Note: I'm not running this under a debugger so I can't confirm the behavior, but this is probably reasonably accurate.
I haven't seen that before, I suspect it's just an internal pointer. Neither thread IDs nor thread handles are usually that large.
There's been no way of getting the apartment type from the current thread, and I've never seen an apartment ID (other than a GUID representing the source/target apartment when marshalling) in native code.
The unit test is most likely running in MTA mode and you have code in it that displays a UI.
One COM context is visual studio, the other is the UI inside your unit test. You can either not display a UI or turn off the MDA.
It looks like the STA COM application does not spin the message loop. This would cause STA COM to just die. I got no idea what the COM context is but it strikes me that you should be able to reproduce your target app to just hang for long periods of time.
Sounds like there is a function that takes more than 60 seconds to run. Have you been able to isolate it?
EDIT This is the guy that wrote COM interop for .NET.
http://blogs.msdn.com/cbrumme/
Have a look at his blog or check out the boards that he frequents. He's written lots of stuff about why COM interop the way it is. It might help to ask this question on one of the Microsoft boards.

.NET CF 2.0: possible single-threaded reentrancy

A simple application is written in CF 2.0. It's single-threaded as far as I'm concerned.
Two parts of the application are of interest: an event handler that handles "Barcode scanned" event raised by a class that represents PDA's barcode scanner (provided by manufacturer), and an event handler for Windows.Forms.Timer that runs every 30 seconds.
Recently the application suffered from a bug the only possible reason for which, as I can see, is processing Barcode Scanned event right in the middle of Timer_Tick event. I was absolutely sure that this was not possible and that one of the events would wait in the queue until first one is handled completely. Windows.Forms.Timer page in MSDN also assures that it's a regular single-threaded timer. Code triggered by Barcode Scanned changes some pieces of the interface, that causes no exceptions, so I'm assuming it's single-threaded as well. No, we're not using DoEvents or such.
Can anybody tell me for sure that such reentrancy is not possible and I should look harder for other possible reasons, or vice versa, that they have suffered from the same problem?
The Windows.Forms timer is going to happen on the UI thread via a call to PostMessage. That is a guarantee. How the "barcode scanned" even comes in is completely up to the developer of the library that's giving you the event. You should certainly not assume that it's going to run in the same context as your timer unless you specifically force it to (via a call to Control.Invoke). Even with that I don't believe you can guaranteee a call order.
If you think re-entrancy might be a cause, the solution is relatively simply - use a Monitor in both handlers (the timer proc and the event) and lock on the same object. That will rule out the possibility that it's a reentrancy issue. If the problem goes away, you know the cause and already have a fix. If the problem persists then you know for certain that it's not reentrancy and you can focus elsewhere.
Pretty much every barcode scanning component i've worked with runs off a background thread, so i'd look at that more closely.