等待事件触发后再继续执行代码

6

我使用C#(visual studio 2010)开发了一个Windows Forms应用程序。该应用程序应该连接到服务器获取数据,然后处理这些数据。

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秒才能获得结果。我该怎么做?


2
server_RecieveMessage 中完成你的任务,而不是等待 SendMessage 返回后再执行。整个异步发送的概念就是为此而生的。请查看什么是 回调函数 - ntohl
只需发送消息,然后等待事件。当事件发生时,我必须处理并发送另一条消息。 - Mohammad Noori
这取决于MyServerSend方法以及ReceiveMessage事件的实现。例如,也许仅使用ReceiveMessage就足以接收消息,无需等待结果;或者发送调用同步,您可以将其输出作为结果。您能否分享更多信息,以便用户根据您的实现而不是猜测来提供答案? - Reza Aghaei
4个回答

10

通过使用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 方法会异步返回控制权,直到消息被接收。当它在下一行继续执行时,您可以修改响应。


2

另一种选择是使用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;
    }

如果我没有得到结果(事件未触发),怎么办?有时候会发生这种情况。 - Mohammad Noori
更新了我的回答,加入了超时功能。 - Fabjan

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

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

接收事件还应该能够处理多线程环境。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接