Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 根据调用事件处理程序的函数返回值_C#_Http_Asp.net Web Api_Rabbitmq - Fatal编程技术网

C# 根据调用事件处理程序的函数返回值

C# 根据调用事件处理程序的函数返回值,c#,http,asp.net-web-api,rabbitmq,C#,Http,Asp.net Web Api,Rabbitmq,我正在使用RabbitMQ(.Net客户端库)将XML消息从WebAPI发布到队列。如果已发布的消息成功持久化到磁盘,我需要发送状态代码200,如果不是,则应返回代码400。RabbitMQ客户端库提供两个单独的事件来发送ACK或NACK事件,指示消息是否保存。因此,在返回http响应之前,我的发布函数需要等待调用两个事件句柄中的任何一个 我怎样才能做到这一点 Api控制器操作 [HttpPost] public HttpResponseMessage SendSomething() {

我正在使用RabbitMQ(.Net客户端库)将XML消息从WebAPI发布到队列。如果已发布的消息成功持久化到磁盘,我需要发送状态代码200,如果不是,则应返回代码400。RabbitMQ客户端库提供两个单独的事件来发送ACK或NACK事件,指示消息是否保存。因此,在返回http响应之前,我的发布函数需要等待调用两个事件句柄中的任何一个

我怎样才能做到这一点

Api控制器操作

[HttpPost]
public HttpResponseMessage SendSomething()
{
    ...
    bool success = _publisher.Publish(bytes);
    if(success) // Send status 200
    else // Send status 400
    ...
}
消息发布代码

public bool Publish(byte[] data)
{
    ..
    channel.BasicAcks += OnAck;
    channel.BasicNacks += OnNack;
    channel.BasicPublish("", "test", null, data);
    ..
    // Depending on if OnAck or OnNack is called I need to return true or false
    return ??
}

private void OnNack(IModel model, BasicNackEventArgs args)
{
    ...
}

private void OnAck(IModel model, BasicAckEventArgs args)
{
    ...
}

如果我读对了,您需要将基于异步回调的例程转换为同步例程。天真的答案是让线程休眠,然后等待某些事情发生:

public bool Publish(byte[] data)
{
    //..
    bool? response = null;
    channel.BasicAcks += (model, args) => response = true;
    channel.BasicNacks += (model, args) => response = false;
    channel.BasicPublish("", "test", null, data);

    while (response == null)
        Thread.Sleep(300);

    return response.Value;
}
然而,这意味着您的响应时间将始终是300ms的倍数,并且您很难实现超时逻辑。一个更好的答案可能是使用。这允许您的回调通过“设置”事件,在收到响应后立即通知被阻止的线程:

public bool Publish(byte[] data)
{
    //..
    bool successful = false;
    var responseReceivedEvent = new ManualResetEvent(false);

    channel.BasicAcks += (model, args) => 
    { 
        successful = true; 
        responseReceivedEvent.Set(); 
    };
    channel.BasicNacks += (model, args) =>
    { 
        successful = false; 
        responseReceivedEvent.Set(); 
    };
    channel.BasicPublish("", "test", null, data);

    responseReceivedEvent.WaitOne();
    return successful;
}

在这两种情况下,您都可以(或应该)实现某种超时/重试逻辑,除非RabbitMQ为您实现这一点。在上一个示例中,您可以使用
WaitOne(int)
WaitOne(TimeSpan)
重载
ManualResetEvent.WaitOne()

这样做非常有效。我已经在玩AutoResetEvent了,但看不到整个画面。我喜欢你用lamda的表达方式。谢谢!:)