Подождите, пока событие не произойдет, а затем продолжите код

Я разработал приложение для Windows Forms с использованием C # (visual studio 2010). Это приложение должно подключиться к серверу и получить данные, а затем обработать эти данные.

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;
    }

Поэтому я хочу подождать после server.Send(Message), пока не получу результат по событию. Иногда требуется 4-5 секунд, пока я не получу результат. Что мне делать?

4 голоса | спросил Mohammad Noori 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2015 09:57:48 +0300 2015, 09:57:48

4 ответа


0

Один из возможных способов сделать это асинхронно - использовать TaskCompletionSource<T> . Это может выглядеть так:

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;
}

Теперь, когда вы хотите вызвать его и асинхронно ожидать результата, вы делаете это:

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

SendMessageAsync будет асинхронно возвращать управление вызывающей стороне до получения сообщения. Затем, как только он возобновится на следующей строке, вы можете изменить ответ.

ответил Yuval Itzchakov 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2015 10:15:01 +0300 2015, 10:15:01
0

Вы должны использовать функцию обратного вызова.

В коде, где находится функция обратного вызова, вы должны реализовать логику.

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 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2015 10:34:41 +0300 2015, 10:34:41
0

Другой вариант - использовать класс AutoResetEvent для синхронизации асинхронных операций:

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 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2015 10:35:11 +0300 2015, 10:35:11
0

Если ваш сервер может обрабатывать асинхронные вызовы. Вы можете использовать любой метод многопоточности, просто вызовите метод Send сервера на другом потоке. Если ваш сервер поддерживает метод SendAsync. Вы также можете использовать это

 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;
}

Событие receive также должно быть в состоянии обрабатывать многопоточную среду.

ответил D J 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 08 Sep 2015 11:23:03 +0300 2015, 11:23:03

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132