private void MessageDispatcher_NOTIFY(MsgSourceInfo src, IMessage imsg) { try { // convert remoting message to the array byte[] buffer = RemotingConvert.ToArray(imsg); // notify IRemotingResponse ro = (IRemotingResponse)Activator.GetObject(typeof(IRemotingResponse), NotifyUrl); ro.ResponseNotify(src, buffer); // echo Trace.WriteLine(string.Format("[{0}]MSMQChannel.Receiver.MessageDispatcher_NOTIFY done, url={1}", ChannelName, NotifyUrl)); } catch(Exception ex) { string strErr = string.Format("[{0}]MSMQChannel.Receiver.MessageDispatcher_NOTIFY failed at url={1}, error={2};", ChannelName, NotifyUrl, ex.Message); WriteLogMsg(strErr, EventLogEntryType.Error); } }
public void MessageWorker(object source) { // scope state int intNumberOfWorkers = 0; bool bTransactional = true; Exception exception = null; IMessage msgReq = null; IMessage msgRsp = null; Message msg = null; MessageQueue mq = source as MessageQueue; MessageQueueTransaction mqtx = new MessageQueueTransaction(); try { // check-in intNumberOfWorkers = Interlocked.Increment(ref m_NumberOfWorkers); // transactional flag bTransactional = mq.Transactional; // echo Trace.WriteLine(string.Format("[{0}]MSMQChannel.Receiver:MessageWorker check-in #{1}, isTxQueue={2}", ChannelName, intNumberOfWorkers, bTransactional)); // begin single transaction if(bTransactional) mqtx.Begin(); // retrieve transactional message (message has been retrieved from the queue) msg = mq.Receive(TimeSpan.FromSeconds(1), mqtx); // signal to manager if(intNumberOfWorkers < MaxNumberOfWorkers) m_EventMgr.Set(); else m_EventMgr.Reset(); // remoting message from the client msgReq = msg.Body as IMessage; // work around!!! msgReq.Properties[MSMQChannelProperties.Uri] = msgReq.Properties[MSMQChannelProperties.ObjectUri]; // option: target object if(NotifyUrl == MSMQChannelDefaults.EmptyStr) { // Dispatch message to the remoting object msgRsp = MessageDispatcher(msgReq, msg.BodyStream); } else { // pack the source info MsgSourceInfo src = new MsgSourceInfo(); src.Acknowledgment = msg.Acknowledgment; src.MessageSentTime = msg.SentTime; src.ResponseQueuePath = msg.ResponseQueue == null ? "null" : msg.ResponseQueue.Path; src.ReportQueuePath = mq.Path; // Call Notification Object MessageDispatcher_NOTIFY(src, msgReq); } // commit transaction (message is going to be removed from the queue) if(bTransactional) mqtx.Commit(); // echo Trace.WriteLine(string.Format("[{0}]MSMQChannel.Receiver.MessageWorker The call has been invoked on {1}", ChannelName, msg.Label)); // response if(AcknowledgeUrl != MSMQChannelDefaults.EmptyStr) { // workaround if(msgRsp != null) { msgRsp.Properties[MSMQChannelProperties.Uri] = msgReq.Properties[MSMQChannelProperties.Uri]; msgRsp.Properties[MSMQChannelProperties.MethodName] = msgReq.Properties["__MethodName"]; msgRsp.Properties[MSMQChannelProperties.TypeName] = msgReq.Properties["__TypeName"]; } // remoting notification MessageDispatcher_ACK(msgRsp == null ? msgReq : msgRsp); } } catch(MessageQueueException ex) { // save for a notification issue exception = ex; // echo Trace.WriteLine(string.Format("[{0}]MSMQChannel.Receiver:MessageWorker error/warning = {1}", ChannelName, ex.Message)); } catch(Exception ex) { // save for a notification issue exception = ex; // echo Trace.WriteLine(string.Format("[{0}]MSMQChannel.Receiver:MessageWorker error/warning = {1}", ChannelName, ex.Message)); } finally { bool bRetryDone = false; if(bTransactional && mqtx.Status == MessageQueueTransactionStatus.Pending) { // check the retry filter int posRules = (RetryFilter == MSMQChannelDefaults.EmptyStr) ? 0 : RetryFilter.IndexOf(exception.Message); if(posRules < 0 && exception.InnerException != null) posRules = RetryFilter.IndexOf(exception.InnerException.Message); // send message to the retry queue if(msg != null && msgReq != null && RetryCounter > 0 && posRules < 0) { // remoting notification bRetryDone = MessageDispatcher_RETRY(mqtx, msg, msgReq); } // commit transaction (message is going to be removed from the queue) mqtx.Commit(); } // exception notification if(exception != null && msg != null && msgReq != null && bRetryDone == false && ExceptionUrl != MSMQChannelDefaults.EmptyStr) { // remoting notification MessageDispatcher_ERROR(msgReq, exception); } // clean-up if(msg != null) msg.Dispose(); // check-out intNumberOfWorkers = Interlocked.Decrement(ref m_NumberOfWorkers); if(intNumberOfWorkers < MaxNumberOfWorkers) m_EventMgr.Set(); else m_EventMgr.Reset(); // echo Trace.WriteLine(string.Format("[{0}]MSMQChannel.Receiver:MessageWorker check-out #{1}, isTxQueue={2}", ChannelName, intNumberOfWorkers, bTransactional)); } }