簡體   English   中英

wcf msmq偵聽器服務刪除消息但不處理

[英]wcf msmq listener service removes messages but doesn't process

我有一個WCF服務,可以在MSMQ中創建私人消息。 消息創建良好,並且可以看到我的客戶端應用程序正在創建的消息。

我也有一個似乎運行良好的MSMQ偵聽器服務。 當我啟動該服務時,它似乎已成功“處理”了隊列中的消息並將其刪除。 但是,我的偵聽器服務的實現似乎未執行。

我對MSMQ還是很陌生,我也不知道為什么從隊列中刪除消息,以及為什么我的偵聽器方法中的代碼沒有得到執行。

以下是我的服務類別...

[ServiceContract(Namespace = ServiceConstants.NAMESPACE, Name = "IOrderService")]
public interface IOrderQueueProcessingService
{

    [OperationContract(IsOneWay = true, Action = "*")]
    void ProcessOrderQueue(MsmqMessage<string> message);

}

public abstract class OrderQueueProcessingServiceBase : ServiceBase, IOrderQueueProcessingService
{
    #region CONSTRUCTORS

    protected OrderQueueProcessingServiceBase() { }

    protected OrderQueueProcessingServiceBase(List<EventRecord> existingList) : base(existingList) { }

    #endregion //CONSTRUCTORS

    #region IOrderQueueProcessingService Members


    [OperationBehavior(TransactionScopeRequired = false, TransactionAutoComplete = true)]
    public virtual void ProcessOrderQueue(MsmqMessage<string> message)
    {
        throw new NotImplementedException();
    }

    #endregion
}

public class OrderQueueProcessingService : OrderQueueProcessingServiceBase
{
    #region Constructors


    public OrderQueueProcessingService() {}

    public OrderQueueProcessingService(List<EventRecord> existingList) : base(existingList) { }


    #endregion

    /// <summary>
    ///     Processes any Orders in the Orders Queue
    /// </summary>
    /// <param name="message"></param>
    public override void ProcessOrderQueue(MsmqMessage<string> message)
    {

        var q = new MessageQueue(@".\private$\msmqdemo/submitorderservice.svc");
        q.Send("hey");
        /*
        using (new Tracer("OrderQueueProcessingService"))
        {
            // add data context to work with.
            using (var unitOfWork = new TLFDataContext())
            {

                var newOrderLines = new List<OrderLineDataContract>
                                {
                                    new OrderLineDataContract
                                        {
                                            C = "test",
                                            IC = "msw",
                                            Qty = 1,
                                            T = "volume" ,
                                            ED = DateTime.UtcNow.AddDays(5)
                                        }
                                };

                var newOrder = new OrderDataContract
                {
                    LIs = newOrderLines.AsEnumerable(),
                    PId = 9323,
                    POId = 8686,
                    S = "new"

                };
                var orderService = new OrderService();
                var createdOrder = orderService.CreateOrder(null, null, newOrder);
                //unitOfWork.SubmitUnitOfWork();

                //return null;
            }
        }*/


    }

}

我注釋掉了我最終嘗試執行的代碼,並用一個簡單的MSMQ消息send替換了它,以進行測試。 這似乎應該正常工作。 任何幫助將不勝感激。

下面的配置設置...

<service name="ServiceImplementation.OrderQueueProcessingService">
    <host>
      <baseAddresses>
        <add baseAddress="https://localhost:9000/OrderQueueProcessingService.svc" />
      </baseAddresses>
    </host>
    <endpoint address="net.msmq://localhost/private/testingqueue/OrderQueueProcessingService.svc" binding="netMsmqBinding" bindingConfiguration="MsmqBindingNonTransactionalNoSecurity" contract="IOrderQueueProcessingService" />
  </service>

我能夠弄清楚我的問題。 QueueOnPeekComplted事件沒有任何事件處理。 我將其添加到Initialize方法中,並能夠成功處理我的消息。 我還添加了對無法處理的消息的處理。 以下是我的OrderQueueProcessingService的新實現。

public class OrderQueueProcessingService : OrderQueueProcessingServiceBase, IDisposable
{
    #region Constructors

    public OrderQueueProcessingService()
    {
        Initialize(ConfigurationManager.AppSettings["OrderQueueProcessingQueueName"]);
    }

    public OrderQueueProcessingService(List<EventRecord> existingList) : base(existingList) {}

    #endregion

    #region Properties

    private MessageQueue Queue { get; set; }

    #endregion

    #region IDisposable Members

    public new void Dispose()
    {
        if (Queue == null) return;

        //unsubscribe and dispose
        Queue.PeekCompleted -= QueueOnPeekCompleted;
        Queue.Dispose();
    }

    #endregion

    private void Initialize(string queueName)
    {
        Queue = new MessageQueue(queueName, false, true, QueueAccessMode.Receive)
                    {
                            Formatter = new XmlMessageFormatter(new[] {typeof (OrderQueueDataContract)})
                    };

        //setup events and start.
        Queue.PeekCompleted += QueueOnPeekCompleted;
        Queue.BeginPeek();
    }

    private static void MoveMessageToDeadLetter(IDisposable message)
    {
        var q = new MessageQueue(ConfigurationManager.AppSettings["OrderProcessingDLQ"], QueueAccessMode.Send)
                    {
                            Formatter = new XmlMessageFormatter(new[] {typeof (OrderQueueDataContract)})
                    };
        q.Send(message, MessageQueueTransactionType.Single);
        q.Dispose();
    }

    /// <summary>
    ///     Processes the specified Order message
    /// </summary>
    /// <param name="orderMessage"></param>
    public override void ProcessOrderQueue(OrderQueueDataContract orderMessage)
    {
        using (var unitOfWork = new MyDataContext())
        {
            switch (orderMessage.M.ToLower())
            {
                case "create":
                    DataAccessLayer.CreateOrder(unitOfWork, orderMessage.O.TranslateToBe());
                    break;
                default:
                    break;
            }
        }
    }

    private void QueueOnPeekCompleted(object sender, PeekCompletedEventArgs peekCompletedEventArgs)
    {
        var asyncQueue = (MessageQueue) sender;

        using (var transaction = new MessageQueueTransaction())
        {
            transaction.Begin();
            try
            {
                using (var message = asyncQueue.ReceiveById(peekCompletedEventArgs.Message.Id, TimeSpan.FromSeconds(30), transaction))
                {
                    if (message != null) ProcessOrderQueue((OrderQueueDataContract) message.Body);
                }
            }
            catch (InvalidOperationException ex)
            {
                transaction.Abort();
            }
            catch (Exception ex)
            {
                transaction.Abort();
            }

            if (transaction.Status != MessageQueueTransactionStatus.Aborted) transaction.Commit();
            else
            {
                using (var message = asyncQueue.ReceiveById(peekCompletedEventArgs.Message.Id, TimeSpan.FromSeconds(30), transaction))
                {
                    if (message != null)
                    {
                        MoveMessageToDeadLetter(message);
                        message.Dispose();
                    }
                }

                EventLog.WriteEntry("OrderQueueProcessingService", "Could not process message: " + peekCompletedEventArgs.Message.Id);
            }
            transaction.Dispose();
        }

        asyncQueue.EndPeek(peekCompletedEventArgs.AsyncResult);
        asyncQueue.BeginPeek();
    }
}

有人看到此實現有任何問題嗎? 我不得不花很多時間弄弄它,但是它已經通過了單元測試和過程測試。

我注意到的一件事是,當我的服務首次啟動時,它會處理隊列中的所有消息。 這可能會阻止我啟動其他服務。 只有在測試時在控制台應用程序中啟動它們時,這才可能是一個問題。 為了安全起見,我最后啟動了此服務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM