views:

363

answers:

1

I'm writing an app that sends messages over a network to another PC that processes the message and sends back a reply (e.g. a boolean or some other data). My network communication subs (based on WCF) just give me the ability to send a message to the other PC and process any received messages.

The issue is that any response received is processed by my designated network message event handler sub, but I have no way of feeding it back to the sub that called for the original message to be sent.

To quickly illustrate, the situation is something like this:

Private Function NetSendMessage(ByVal message As String) As Boolean 
    'Send network message to PC with device connected 
    '.... 
    'returns true if message sent 
End Function 

Private Sub NetMessageReceived(ByVal sender As Object, ByVal e As MessageEventArgs) Handles NetComm.OnReceiveMessage 
    'Handles incoming messages 
    '.... 
End Sub 

Private Function MoveForward() As Boolean 
    Return (MoveLeftWheel() And MoveRightWheel()) 
End Function 

Private Function MoveLeftWheel() As Boolean 
    If NetSendMessage("MoveLeftWheel") = False Then Return False 

    'Network message went through, now we need to know if the command was executed, which the remote PC will tell us 
    Return ______  *(here is the trouble-- how do I get the boolean response from the other side as to whether this worked or not?)*
End Function 

Private Function MoveRightWheel() As Boolean 
    If NetSendMessage("MoveRightWheel") = False Then Return False 

    Return ______ 
End Function

The solutions I've thought of so far are more complex than this probably needs to be.

One idea I had was to add an ID number to identify each message (which the other side would include in its response), and then I'd have an ArrayList for a "message queue." The NetMessageReceived sub would add any new message to this ArrayList, and any function that wants a reply would monitor the queue to see if its response arrived. It'd be something like this:

Private NetMessageQueue as New ArrayList 
Private LatestMessageID as Integer 

Private Sub NetMessageReceived(ByVal sender As Object, ByVal e As MessageEventArgs) Handles NetComm.OnReceiveMessage 
    'Handles incoming messages 
    NetMessageQueue.Add(e.Message.ToString) 
End Sub 

Private Function MoveLeftWheel() As Boolean 
    'Send network message to robot PC 

    Private MyMessageID as Integer = LatestMessageID + 1 

    NetSendMessage(MyMessageID & "|" & "MoveLeftWheel") 

    Do 
            For Each msg As String in NetMessageQueue 
                    If msg.Split("|")(0) = MyMessageID.ToString Then 
                            'This is the response message we're waiting for 
                            Return Boolean.Parse(msg.Split("|")(1)) 
                    End If 
            Next 
    Loop 
End Function

This seems like a very cumbersome / unnecessarily taxing way to do this. I was thinking along the lines of maybe add a NetSendReceive function that, say, MoveRightWheel could call; NetSendReceive would call NetSendMessage, monitor the message queue for its response (perhaps via a delegate/IAsyncResult), and then return the response message (to MoveRightWheel, which would be waiting for it).

There's probably a better way to do this- any ideas?

+1  A: 

What if you wrap all of this in a class? Then the idea would be that you'd only have one "NetComm" object in each instance. Say you call the class MessagingUtility. And whenever you want to send a new message you'll have to call

Dim myMessage As New MessagingUtility()
myMessage.NetSendMessage("Hello World")

Or something like that.

This will prevent any possibility of you losing track of the context of a message when a lot of other messages are being sent around the same time. Because after all, every property of a given message you'll ever want will be contained neatly in the myMessage object.

Steve Wortham