Sina Karvandi
Sina Karvandi

Reputation: 1102

Wait for another method to invoke and then continue with result

I am trying to invoke a method from another .dll file . It is sending a message through the VPN then Return the RecievedMessage from another computer.

As you now it takes time to sending and receiving message and VpnObject just send message and I should wait for listener to invoke the RecievedMessage.

This method is like this!

    public string RecievedMessage()
    {
        string Recieved ;
        // Some VPN Code  and then return the result;
        return Recieved;
    }

    public string SendAndRecieveMessage(string MessageToSend)
    {
        string RecievedAnswer = string.Empty;

        // Now Sending Message through the VPN
        VpnObject.SendMessage(MessageToSend);

        //Then want to Recieve the answer and return the answer here .

        return RecievedAnswer;
    }

I'm just thinking how can wait for RecievedMessage to invoke then return the result .

You know it is simple to use a variable and assign it value and check for while but it reduced the performance dramatically .

Is there anyway to continue from SendAndRecieveMessage just when RecievedMessage invoked ? (I think it is something with async and await but don't know how!)

Edit :VpnObject is just a sender and receiver through the vpn . it contains a simple socket send and a listener that invoke a method(RecievedMessage) when new message received .

Upvotes: 5

Views: 1969

Answers (2)

Alan
Alan

Reputation: 46903

You know it is simple to use a variable and assign it value and check for while but it reduced the performance dramatically .

A spin while loop is definitely not the way to implement this. Even with a sleep, it's clunky, and C# has multiple ways to solve this problem.

It's not entirely clear how your VPN Send and Receive method works, but the idea for solving this is to either use a callback approach, or as you noted, use C# async framework.

Without more details on the VPN Object, I'll just have to have some stub methods. The idea is to create a Task that returns the string, mark it as an async task, then await for it to complete. In your case, the task is receiving the VPN response string.

Something like this.

public Task<string> ReceivedMessage()
{
    //get the response from the VPN Object.
    string Received = VpnObject.GetResponse(); 
    var ts = new TaskCompletionSource<string>();
    ts.SetResult(Received);

    // Some VPN Code  and then return the result;
    return ts.Task;
}

public async Task<string> SendAndReceiveMessageAsync(string MessageToSend)
{
    string result = string.Empty;

    // Now Sending Message through the VPN
    VpnObject.SendMessage(MessageToSend);

    result = await ReceivedMessage();

    return result;
}

Upvotes: 0

user1726343
user1726343

Reputation:

Whether or not you have an alternative to polling depends on whether the library you are using provides any events or callbacks that will tell you when the request has completed.

Either way, the standard approach to exposing the deferred result of an asynchronous operation is to use a Task. Your method signature would look like this:

public Task<string> SendAndRecieveMessage(string MessageToSend)

Now, how you actually implement the method depends on what API VpnObject exposes. TaskCompletionSource is very useful for this kind of thing.

If VpnObject has an event that fires when the request completes:

public Task<string> SendAndReceiveMessage(string messageToSend)
{
    var tcs = new TaskCompletionSource<string>();
    ...
    VpnObject.OnMessageReceived += (s, e) => tcs.SetResult(e.Message);
    ...
    return tcs.Task;
}

If VpnObject can accept a callback that it will invoke when the request completes:

public Task<string> SendAndReceiveMessage(string messageToSend)
{
    var tcs = new TaskCompletionSource<string>();
    ...
    VpnObject.OnMessageReceived(message => tcs.SetResult(message));
    ...
    return tcs.Task;
}

If VpnObject doesn't support any of this, you can fall back to polling:

public async Task<string> SendAndReceiveMessage(string messageToSend)
{
    var tcs = new TaskCompletionSource<string>();
    ...
    while(!VpnObject.IsMessageReceived)
        await Task.Delay(500); // Adjust to a reasonable polling interval
    ...
    return VpnObject.Message;
}

Upvotes: 2

Related Questions