System.IO.Ports.SerialPort Write() Timeout - c#

The program I'm working on in C# (.Net Framework 2.0) calls for the ability to switch over to a 'remote mode' and send ascii data to another screen via Bluetooth. I'll start by saying I'm not a very experienced programmer, and I know nothing about networking, but after fooling around with the SerialPort class yesterday I was able to work up a little chat program that worked nicely between two Bluetooth-connected devices.
The chat program, however, only sent data when the user hit a button to "send" data. If the two devices weren't properly connected I just threw a TimeoutException along with an error message. The program I'm working on now is much larger, and tries to write data constantly so long as it has the COM port open.
That means if the two devices aren't immediately connected, it has to throw a TimeoutException, and it will continue to throw it, again and again until they ARE properly connected. That's totally unacceptable. It slows the program down to the point where it isn't usable, and litters the Debug output with "TimeoutException Thrown Here" error messages.
Is there a better solution for how to do this? Some way that I can get it to only write the data out if I can confirm that the two devices are connected, without constantly checking (and subsequently getting Timeout Errors while checking).

No. A serial connection is stateless.
This means you don't know if someone is on the other side. All you can do is sending something out and take a look if something meaningful is coming back.
The easiest example for this is the good old analog modem. To find out if it is connected is to send out a AT and check if an OK comes back.
So your solution is the right one, but maybe not properly implemented. You should put your connection built-up sequence into a BackgroundWorker. So these tries will be done in another thread while your GUI stays responsive to the user.

Related

Solution needed for C# form serial port hang due to serial port reception and multi-threading

Im actually kind of stuck here in this small piece of application.
It's actually meant to read serial port data which comes at the rate of 1Hz from a hardware and update it on the two graphs and data gridview in the main form. The first form actually auto-detects your serial port and awaits you to click next and proceed to the application. In case it is not able to detect your serial port it throws an error.
After reaching the main form, you'll have to press the start button to start the serial port reception. The hardware actually sends a three digit number in the format, "100\n 200\n 300\n...." for every one second interval. The two graphs and the Datagridview on the tabs above updates every time a new data enters in.
Since, one second is too short of an interval to update the two graphs, update datagridview, compare the input value to some alert settings,etc., the application was multi-threaded. The graph update method was split into a separate thread and even the serial port data reception is handled by data_received event which is also by default a separate thread.
But, here's the problem, the application runs well in debug mode. However, when I run it after publishing, the serial data reception alone hangs after some random time interval. I believe this is due to some data misinterpretation or multi-threading time allowance issue or something. I would be really greatful if someone could figure out what the problem is.
I have affixed my source code. Feel free to use it for your applications also. In case the app shows error on visual studio. Please include Zedgraph.dll into your form controls from the debug or release folder.
Click here for entire Application in zip file
Thanks in advance!

Sending WM_COPYDATA but getting WM_ACTIVATEAPP on the receiving side

I have the following scenario:
My app gets some data from the command line.
After getting executed by the first time, my app runs always one instance and that instance will be in memory until the use explicitly tells it to shutdown instead of just hiding the form when not needed.
When the user tries to run the app a second time, the process starts, checks if there is another one in memory and if that is true, it sends a WM_COPYDATA message to the process in memory with the data it got from the command line and exits.
That all works well when the it«s the user who runs the app.
I needed to ran it from the Microsoft Word 2003 toolbar so i used a "Add-in" for that. The problem is that when my app is started from that Add-In (using Process class), it seems that the process already in memory gets a WM_ACTIVATEAPP message instead of a WM_COPYDATA one, so i can't get the needed data sent from the process started by the Add-In.
I have no idea on why is that happening and how to fix it. I've googled for hours and nothing helped...
Can anyone help?
Getting a WM_ACTIVATEAPP message is quite normal, part of the usual notifications that Windows sends. Don't assume that the first message you'll get is WM_COPYDATA, keep looking. If you don't get it at all then the window handle that you used to send the message was wrong. Which is a very common problem, it is not that easy to accurately find a window back.
The .NET framework already has very good support for single-instance apps that can retrieve the command line from a second instance. Consider using it instead. Check this blog post.

.Net SerialPort still locked after application is killed

I have an application which calls SerialPort.Open() ...
This works fine and data is read/written through the port.
However if a user decides to kill the Application through the TaskManager the application will close without calling my destructor calling SerialPort.Close().
This in turn (only sometimes) causes the following error:
Access to the port 'COM2' is denied.
This occurs on re-startup of the application.
I've read enough posts to know that this wouldn't happen if .Close() was properly called.
So far I have handled this by having a timer which reattempts the .Open().. which eventually succeeds (that is I think it does most of the time).
My question is this:
Is there a DLLImport method which will allow me to free the Comm port resource?
I rubbed my crystal ball and it revealed that you are using a USB driver that emulates a serial port, that the user decided it was a good idea to kill the process because she jerked the USB connector out of the socket and that she is running a pre-Vista version of Windows.
Roughly any two combinations out of that list. Yes, doesn't work, you cannot kill a process when it has a kernel thread going that is completing an I/O request that cannot finish. You can tell from TaskMgr.exe when you use View + Select Columns and tick Handles. The process will zombie with one handle opened. Won't close until the driver actually lets go. Won't happen, USB drivers suck like that.
Starting the program again will bomb, the first instance of the process still has the port opened. Access denied.
Tell the user to keep her hands off the connector. Or buy another one from a different manufacturer. You can help by adding a "Safely Remove Hardware" menu option to your program. That calls the SerialPort.Close() method. Call Sleep(2500) and display a message box that it is okay to unplug it.

Is it correct to leave COM1 open all along the program?

Is it correct to leave COM1 open all along the program ?
and close it only in exit from the program ?
thank's in advance
It is quite common to do this, because there will be overhead associated with the open/close operation. You might end up confusing the OS opening and closing it too frequently.
So yes... open it, keep it open (unless there is an error), and close it when you are finished.
The only reason you would close it during the application, is to let other applications share the port.
So far i would say that Fuzz and RaYell are both right (depending on the concrete situation). So for my projects i usually provide a button on my form where you can connect and disconnect the serial port. So you're also able to provide a list of available com ports, where the user can select the desired port and afterwards press connect. So the user is able to decide in the concrete situation if it is needed to close the port or not.
Maybe for more convenience you can also save the last settings, provide some command line arguments, etc. for a better user experience.
If you do that other applications won't be able to use that port until you shutdown your app. That doesn't sound like a good idea, does it? I think you should open it, get/send the data and close it immediately after you are done with it.
It depends on how the hardware attached to it works. When you open/close a port, a hardware signal can be triggered by the UART on one of the pins. I once had a device that would reset itself whenever the port was closed. So, YMMV.
It depends on what your program does and how long it's going to run for. If you're communicating with a modem, for instance, you probably don't want other applications to interrupt your datastream, so in that case you'd keep it open the whole time and close it when finished.
If you're monitoring the status of some external hardware, and only need to check it periodically, it's better to open and close it every time you access it, so other programs can also access it if necessary.

How to you determine when Windows is done rebooting?

I am using the Windows Update API to update a bunch of VM's. With Windows Update comes the inevitable reboots. Can anyone think of a way that I could tell from a remote server if the windows box has indeed finished its reboot? All ideas or thoughts would appreciated.
EDIT:
Because the VM's are in Lab Manager and using a fenced configuration, WMI will not work, and although I thought about using the VM to send a signal when it was back up. There would have been no way to reliably know who to notify as the app waiting for the machine could be on any number of machines so it just didn't seem reasonable. However time is not essential (and even though I know this will bite me sometime when a Service Pack comes down) I have had good success with the PING and then wait 5 minutes so far, so I am going to use that for now. If I run into exceptions I will then try to implement the VM notfiying the world when it comes back up. Thanks to all.
Just wait for it to respond to a ping.
In light of your comments:
1 - Use this script
2 - If you get any errors with that script, follow these instructions.
Check for this event in the event log:
Event Type: Information
Event Source: EventLog
Event Category: None
Event ID: 6005
Date: 7/27/2007
Time: 12:56:24 PM
User: N/A
Computer: IWSDEV
Description:
The Event log service was started.
A more general version of this question is How do I know if a system has powered on?
The reality is that you can't know when it is done booting. The boot process is pretty asynchronous and so whatever criteria you use to determine that it is done "booting" could happen before something else completes.
What I would recommend is determine what you actually want to know. What specifically is it you are waiting for? Find a way to determine whether this has taken place and forget worrying about "booting".
If you just need to know that the machine is back up but maybe hasn't completed all of the post-boot loading, put something in the startup sequence or a service that signals your code. When this signal takes place, take whatever action you need to.
You could install a startup program or service on the machine to send an email or some type of network based posting everytime it restarts.
Windows is done rebooting only slightly before it'll need rebooting again :-)
If you're specifically looking to query the status of VMs then you should check out these links which deal with the API for Virtual Server 2005:
The IVMVirtualMachine Interface...
http://msdn.microsoft.com/en-us/library/aa368465(VS.85).aspx
... has a property called State...
IVMVirtualMachine::State Property
http://msdn.microsoft.com/en-us/library/aa368637(VS.85).aspx
... which will return a value from the VMVMState Enumeration...
http://msdn.microsoft.com/en-us/library/aa368922(VS.85).aspx
At a more general level, you should probably define how much of Windows you want up and running. Do you consider network stack ready to be "rebooted" or do you need IIS/SQL or some other application level service up?
I'd probably write an app that checks the "heart-beat" of your servers - that app could well be the same one that's invoking the Windows Update stuff. You'd then get yourself a nice "console" showing you the status of your servers. The heart-beat app could ping a server, hit a static html page, hit the remote event log, use WMI or whatever you define as enough to consider your server rebooted.

Categories

Resources