Azure Service Bus - 使用OnMessage()方法接收邮件

时间:2016-11-14 20:05:52

标签: c# azureservicebus

MS documentation之后,从订阅接收消息并不困难。但是,如果我希望我的应用程序每次发布新消息时都会收到消息 - 持续轮询。因此 SubscriptionClient 类的 OnMessage()方法。

MS documentation说: ...当调用OnMessage时,客户端启动内部消息泵,不断轮询队列或订阅。此消息泵由无限组成发出Receive()调用的循环。如果调用超时,它会发出下一个Receive()调用....

但是当应用程序运行时,只有在调用 OnMessage()方法时才会收到最新消息。发布新消息时,常量轮询似乎不起作用。在尝试了许多不同的方法之后,我可以使这项工作成为唯一的方法并让应用程序在接收到新消息时作出反应,将代码放入具有无限循环的单独任务中。在如此多的层面上,这似乎完全错误了!(见下面的代码)。

任何人都可以帮我修正我的代码或发布工作样本来完成相同的功能而不需要循环吗?谢谢!

 public void ReceiveMessageFromSubscription(string topicName, string subscriptionFilter)
        {
            var newMessage = new MessageQueue();
            int i = 0;

            Task listener = Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    SubscriptionClient Client = SubscriptionClient.CreateFromConnectionString(connectionString, topicName, subscriptionFilter);

                    Dictionary<string, string> retrievedMessage = new Dictionary<string, string>();

                    OnMessageOptions options = new OnMessageOptions();
                                     options.AutoComplete = false;
                                     options.AutoRenewTimeout = TimeSpan.FromMinutes(1);

                    Client.OnMessage((message) =>
                    {
                        try
                        {
                            retrievedMessage.Add("messageGuid", message.Properties["MessageGuid"].ToString());
                            retrievedMessage.Add("instanceId", message.Properties["InstanceId"].ToString());
                            retrievedMessage.Add("pId", message.Properties["ProcessId"].ToString());
                            retrievedMessage.Add("processKey", message.Properties["ProcessKey"].ToString());
                            retrievedMessage.Add("message", message.Properties["Message"].ToString());

                            newMessage.AnnounceNewMessage(retrievedMessage); // event ->

                            message.Complete(); // Remove message from subscription.
                        }
                        catch (Exception ex)
                        {
                            string exmes = ex.Message;
                            message.Abandon();
                        }

                    }, options);

                    retrievedMessage.Clear();

                    i++;

                    Thread.Sleep(3000);
                }

            });
        }

1 个答案:

答案 0 :(得分:12)

你的代码有一些问题要解决 -

  • 它落空了,我假设你的应用程序然后退出 - 或者 至少正在侦听消息的线程终止。
  • 你的while循环不断重复代码来连接消息处理程序, 你只需要这样做一次。
  • 您需要一种方法来保持调用堆栈的活动,并防止您的应用程序垃圾收集您的对象。

以下内容应该会让您走向成功之路。祝好运。

 ManualResetEvent CompletedResetEvent = new ManualResetEvent(false);
    SubscriptionClient Client;

    public void ReceiveMessagesFromSubscription(string topicName, string subscriptionFilter, string connectionString)
    {
        Task listener = Task.Factory.StartNew(() =>
        {
            // You only need to set up the below once. 
            Client = SubscriptionClient.CreateFromConnectionString(connectionString, topicName, subscriptionFilter);

            OnMessageOptions options = new OnMessageOptions();
            options.AutoComplete = false;
            options.AutoRenewTimeout = TimeSpan.FromMinutes(1);
            options.ExceptionReceived += LogErrors;

            Client.OnMessage((message) =>
            {
                try
                {
                    Trace.WriteLine("Got the message with ID {0}", message.MessageId);
                    message.Complete(); // Remove message from subscription.
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("Exception occurred receiving a message: {0}" + ex.ToString());
                    message.Abandon(); // Failed. Leave the message for retry or max deliveries is exceeded and it dead letters.
                }

            }, options);

            CompletedResetEvent.WaitOne();
        });
    }

    /// <summary>
    /// Added in rudimentary exception handling .
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="ex">The <see cref="ExceptionReceivedEventArgs"/> instance containing the event data.</param>
    private void LogErrors(object sender, ExceptionReceivedEventArgs ex)
    {
        Trace.WriteLine("Exception occurred in OnMessage: {0}" + ex.ToString());
    }

    /// <summary>
    /// Call this to stop the messages arriving from subscription.
    /// </summary>
    public void StopMessagesFromSubscription()
    {
        Client.Close(); // Close the message pump down gracefully
        CompletedResetEvent.Set(); // Let the execution of the listener complete and terminate gracefully 
    }

或者,您可以使用ReceiveBatch以更传统的方式将消息分块:

var messages = await queueClient.ReceiveBatchAsync(10, TimeSpan.FromSeconds(30),
                                                       cancellationToken);