有很多方法可以做到这一点。例如,您可以将EventingBasicConsumer 与ManualResetEvent 一起使用,如下所示(这仅用于演示目的 - 最好使用以下方法之一):
var factory = new ConnectionFactory();
using (var connection = factory.CreateConnection()) {
using (var channel = connection.CreateModel()) {
// setup signal
using (var signal = new ManualResetEvent(false)) {
var consumer = new EventingBasicConsumer(channel);
byte[] messageBody = null;
consumer.Received += (sender, args) => {
messageBody = args.Body;
// process your message or store for later
// set signal
signal.Set();
};
// start consuming
channel.BasicConsume("your.queue", false, consumer);
// wait until message is received or timeout reached
bool timeout = !signal.WaitOne(TimeSpan.FromSeconds(10));
// cancel subscription
channel.BasicCancel(consumer.ConsumerTag);
if (timeout) {
// timeout reached - do what you need in this case
throw new Exception("timeout");
}
// at this point messageBody is received
}
}
}
正如您在 cmets 中所述 - 如果您希望在同一个队列中有多个消息,这不是最好的方法。好吧,无论如何这都不是最好的方法,我包含它只是为了演示ManualResetEvent 的使用,以防库本身不提供超时支持。
如果您正在执行 RPC(远程过程调用,请求-回复) - 您可以在服务器端使用 SimpleRpcClient 和 SimpleRpcServer。客户端将如下所示:
var client = new SimpleRpcClient(channel, "your.queue");
client.TimeoutMilliseconds = 10 * 1000;
client.TimedOut += (sender, args) => {
// do something on timeout
};
var reply = client.Call(myMessage); // will return reply or null if timeout reached
更简单的方法:使用基本的Subscription 类(它在内部使用相同的EventingBasicConsumer,但支持超时,因此您无需自己实现),如下所示:
var sub = new Subscription(channel, "your.queue");
BasicDeliverEventArgs reply;
if (!sub.Next(10 * 1000, out reply)) {
// timeout
}