5

I developed an application with Windows Forms using C#(visual studio 2010). This application should connect to a server and get data, then process that data.

public partial class Form1 : Form
{
    public string Result = "";

    MyServer server = new MyServer();

    public Form1()
    {
        InitializeComponent();

        server.RecieveMessage += new MyServer.RecieveMessageEventHandler(server_RecieveMessage);
    }

    void server_RecieveMessage(object sender, string message)
    {
        Result = message;
    }


    public string SendCommand(string Command)
    {


        server.Send(Command);

        //wait untill RecieveMessage event raised


        //process Data is recieved

        server.Send(AnotherCommand);

        //wait untill RecieveMessage event raised


        //process Data is recieved

        ....

            //till i get what i want
        return Result;
    }

So I want to wait after server.Send(Message) until I get the result on event. Sometimes it takes 4 to 5 seconds until I get the result. What do I have to do?

Mohammad Noori
  • 137
  • 2
  • 10
  • 2
    Do Your stuff in the `server_RecieveMessage`, not when the SendMessage returns. The whole async send idea is about that. Check for what is a [callback function](http://stackoverflow.com/questions/2139812/what-is-a-callback). – ntohl Sep 08 '15 at 07:06
  • send just send the message.and i have to wait for event.when it comes i have to process and send another message. – Mohammad Noori Sep 08 '15 at 07:14
  • It depends on the implementation of `MyServer` and `Send` method and `ReceiveMessage` events. For example maybe `ReceiveMessage` is enough for receiving message and no need to wait for result, or maybe send calls sync and you have result as its output. Can you share more so users will provide answer based on your implementation not their guess. – Reza Aghaei Sep 08 '15 at 07:16

4 Answers4

9

One possible way of doing this asynchronously is using TaskCompletionSource<T>. It could look like this:

public async Task<string> SendMessageAsync(string message)
{
    var tcs = new TaskCompletionSource<string>();

    ReceiveMessangeEventHandler eventHandler = null;
    eventHandler = (sender, returnedMessage) =>
    {
        RecieveMessage -= eventHandler;
        tcs.SetResult(returnedMessage);
    }

    RecieveMessage += eventHandler;

    Send(message);
    return tcs.Task;
}

Now, when you want to call it and asynchronously wait for the result, you do this:

public async void SomeEventHandler(object sender, EventArgs e)
{
    var response = await server.SendMessageAsync("HelloWorld");
    // Do stuff with response here
}

SendMessageAsync will asynchronously yield control back to the caller until the message is received. Then, once it resumes on the next line, you can alter the response.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
2

Other option would be to use AutoResetEvent class to synchronize your async operations:

public partial class Form1 : Form
{
    public string Result = "";
    private int timeOut = 10000;

    MyServer server = new MyServer();
    AutoResetEvent res = new AutoResetEvent(false);

    public Form1()
    {
        InitializeComponent();   

        server.RecieveMessage += new MyServer.RecieveMessageEventHandler(server_RecieveMessage);
    }

    void server_RecieveMessage(object sender, string message)
    {
        Result = message;
        res.Set();
    }


    public string SendCommand(string Command)
    {        
        server.Send(Command);
        res.WaitOne(timeOut);

        //wait for 10 seconds or untill RecieveMessage event raised


        //process Data is recieved

        server.Send(AnotherCommand);
        res.WaitOne(timeOut);    

        //wait for 10 seconds or untill RecieveMessage event raised


        //process Data is recieved

        ....

            //till i get what i want
        return Result;
    }
Fabjan
  • 13,506
  • 4
  • 25
  • 52
0

You should use the callback function.

In the code, where the callback function is, You should implement the logic.

void server_RecieveMessage(object sender, string message)
{
    Result = message; // You have Your incoming data here. If this code runs, You have already waited the next message.
    //process Data is recieved
    if (till i get what i want)
    {
        // Use Result as final value.
        // Close connection.
        server.RecieveMessage -= server_RecieveMessage;
    }
}
ntohl
  • 2,067
  • 1
  • 28
  • 32
0

If your server can handle asychronous calls. You can use any of the multithreading technique just you have to call Send method of server on other thread. If your server support SendAsync method. You can use that also

 public partial class Form1 : Form
 {
 public string Result = "";

 MyServer server = new MyServer();

public Form1()
{
    InitializeComponent();

    server.RecieveMessage += new MyServer.RecieveMessageEventHandler(server_RecieveMessage);
}

void server_RecieveMessage(object sender, string message)
{
    Result = message;
}


public string SendCommand(string Command)
{

    Task.Factory.StartNew(() =>
    server.Send(Command)
    );

    //wait untill RecieveMessage event raised


    //process Data is recieved

    Task.Factory.StartNew(() =>
    server.Send(AnotherCommand));

    //wait untill RecieveMessage event raised


    //process Data is recieved

    ....

        //till i get what i want
    return Result;
}

The receive event also should be able to handle multi threading env.

D J
  • 6,908
  • 13
  • 43
  • 75