kejpa Posted March 16, 2006 Posted March 16, 2006 Hi, I'm using a derived Serialports class for handling all talking/listening on a Serialport. This class is referenced from a number of other classes. What I basically want is that it handles each call separately, send a command, wait for a respose the given time and return the response or a timeout exception. If another object is trying to talk during this time it's put on hold, and if the second objects Write timeout time is reached while on hold it will get a TimeOutException too. One thing that complicates it is that the application have to move on as if no waiting is done. Another thing is I want it simple... try sResponse=myCommPort.CommandResponse(sCommand) catch ex as TimeOutException Debug.Print"Timed out" catch ex as Exception Stop end try Any help appreciated /Kejpa Quote
mskeel Posted March 16, 2006 Posted March 16, 2006 The first thing that comes to my mind with what you described is to set up something like a signal queue. Basically, this would be a class that your application talks to and that handles all the communication between the serial port and your application. Your application would fire off a command and keep doing whatever it needs to do. Meanwhile, in another thread the signal queue would run the code that you printed above (or something like it). When you get some kind of feedback from the serial port commands, you'll pass information back to the calling class, probably via events. While all of this is going on for that first command you entered, the user could still enter other commands. Those other commands just get queued up in your signal queue class and once the first command is completed and reported back to the application, the next command is run (or possibly not run depending on error conditions). I'm not too familiar with design patterns, but I've seen this done in a lot of places (at least in code in my industry) so you might be able to find more information on this potential implementation on the web. Quote
kejpa Posted March 17, 2006 Author Posted March 17, 2006 The first thing that comes to my mind with what you described is to set up something like a signal queue. Basically' date=' this would be a class that your application talks to and that handles all the communication between the serial port and your application. [/quote'] Correct, that's my approach too, but I can't get it further. I seems to be painting myself into different corners most of the time, (the other times I just get tied up by all the threads created ;)) Your application would fire off a command and keep doing whatever it needs to do. Meanwhile' date=' in another thread the signal queue would run the code that you printed above (or something like it). When you get some kind of feedback from the serial port commands, you'll pass information back to the calling class, probably via events.[/quote'] Not so sure about using events as all objects would receive the notification, and it's actually just the caller that needs to be noticed. Thanx /Kejpa Quote
mskeel Posted March 17, 2006 Posted March 17, 2006 Not so sure about using events as all objects would receive the notification' date=' and it's actually just the caller that needs to be noticed.[/quote'] True, the event is available to all classes, but only classes with valid event handlers will take any action. So if you only want the calling class to handle the event, then that would be the only place that gets an event handler and that will be the only class that really cares that an event was fired. A delegate passed to the signal queue by the calling class is another way to do it, but with threading I think you'll have to fire an event at some point to get the message back to your display thread in a thread-safe way. Quote
kejpa Posted March 17, 2006 Author Posted March 17, 2006 Hi! The problem is that I probably will have a couple of different classes all with a couple of instances that will use the call. With event handlers I'd have the response in half a dozen places it shouldn't be. Is passing a delegate a way to ensure that only the calling object will receive the response? Many thanx! /Kejpa Quote
mskeel Posted March 17, 2006 Posted March 17, 2006 Is passing a delegate a way to ensure that only the calling object will receive the response?It's one way you can do it, yes. A possible solution might look like this in psuedo code: Class CallerOne //One class that can call the serial port. { SignalQueue queue Delegate Result(String feedback) //this would actually need to be in a different place so more than just this class could use it. Function TalkToSerialPort() { this.queue.Talk(new Signal(command, AddressOf GetResults)) //put your signal in the queue with the command and pointer to the method of getting results back to this caller. } Function GetResults(String feedback) { Give Results to display //You will probably need to throw an event here to avoid concurency issues. The display class would be the only class to catch that event. } } Class SignalQueue { Function Talk(Signal command) { this.Enqueue(command) } Function ProcessNextCommand() //When it's time to process another command... { nextSignal = this.Dequeue //returns something of type Signal result = Run(nextSignal.command) //send the command to the serial port ProcessResult(result) //failure, you'll probably want to bail out and send a big fat exception or event to kill everything nextSignal.giveResults(result) //using the delegate, give the result back to the caller. } } Class Signal { String command //the command to be run Result giveResults //a pointer to the class to give results to }I used C# BBcode block for the syntax highlighting, it isn't actually C# code. There still are some details that will need to be worked out, but hopefully this conveys the general gist. Quote
kejpa Posted March 20, 2006 Author Posted March 20, 2006 It's one way you can do it, yes. A possible solution might look like this in psuedo code: I used C# BBcode block for the syntax highlighting, it isn't actually C# code. There still are some details that will need to be worked out, but hopefully this conveys the general gist. Hi mskeel! I've got it working now, thanks to you. With some tweaking I got it into my existing Comm-wrapper too so now I'm really pleased. /Kejpa :D Quote
kejpa Posted March 21, 2006 Author Posted March 21, 2006 Command/Response -revisited... Hi, I was sooo happy yesterday when I got it tweaked into my existing CommPort class. But today I realize that I need the response in the statements following the call :( 'UI try sResponse=myCommPort.CmdResponse(sCommand) select case sResponse case "<" DoThis case "!" DoThat case "?" DoSomethingElse end select catch ex as TimeOutException console.writeline(ex.message) end try Asynchonous handling comes to mind, but I can't find any good samples. The UI calls once a second and the calls should pile up but if no respose has come within 1.5 sec it should timeout and process next message not that has not timed out. The message queue was pretty but I couldn't get the response back to the calling method :( TIA /Kejpa Quote
mskeel Posted March 21, 2006 Posted March 21, 2006 These look like two decent tutorials on asynchrounous callbacks (events) and delegates: The code project Dev City I think what you want to do is fire and forget the command from the gui, then have a differnet method wait for the response which will either come synchronously via a delegate or asynchronously via an event. Here's an example of what the asynchrounous code might look like in the GUI. 'UI Sub RunCommand(ByVal command As String) myCommPort.CmdResponse(command) End Sub ' Sub HandleCommandResponse(ByVal sender As Object, ByVal response As String) Handles CommandResponseEvent Select Case sResponse case "<" DoThis case "!" DoThat case "?" DoSomethingElse case Default Fail() end select End SubWaiting for the time out exception should probably happen when you are sending the command to the serial port. The GUI isn't waiting for anything to happen, but it does need to be ready to get a response. All of the really hard stuff, waiting for a response, determining if there was a timeout, and possibly even interpriting the response (return something like a pass/fail/timeout enum to the gui for example) should probably be happening in the class that sends the commands to the serial port. Hopefully that makes sense. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.