Obecnie mam problem z utratą wiadomości. Ten błąd występuje rzadko, ale zdarza się tak często, że może być denerwujący. Oto kontekst wydania:Czy można utracić wiadomości za pomocą MSMQ MessageQueue.Peek z przekroczonym limitem czasu?
- Włączyłem dziennik wiadomości w goldmine_service_queue, MSMQ na serwerze Windows 2003.
- Mogę udowodnić, że wiadomość jest wstawiana do goldmine_service_queue, ponieważ wiadomość pojawia się w dzienniku wiadomości. Ta informacja podaje czas informacji o tym, kiedy wiadomość zniknęła.
- Funkcje rejestrowania używają http://logging.apache.org/log4net/index.html
- Dzienniki nie wyświetlają błędów.
- Funkcja pracownika (pokazana poniżej) wykonuje się w wątku usługi systemu Windows. Odpowiada za podgląd wiadomości (elementów pracy) z kolejki i ich przetwarzanie.
- Z dzienników podejrzewam, że mój problem może dotyczyć zachowania MessageQueue.Peek i przekroczenia limitu czasu.
Czy możliwe jest wystąpienie limitu czasu i komunikatu w tym samym czasie? Czy istnieje lepszy sposób na obsłużenie sprawdzania zatrzymania usługi, aby uniknąć tego błędu?
private void workerFunction()
{
logger.Info("Connecting to queue: " + Settings.Default.goldmine_service_queue);
MessageQueue q = new MessageQueue(Settings.Default.goldmine_service_queue);
q.Formatter = new ActiveXMessageFormatter();
while (serviceStarted)
{
Message currentMessage = null;
try
{
currentMessage = q.Peek(new TimeSpan(0,0,30));
}
catch (System.Messaging.MessageQueueException mqEx)
{
if (mqEx.ToString().Contains("Timeout for the requested operation has expired"))
{
logger.Info("Check for service stop request");
}
else
{
logger.Error("Exception while peeking into MSMQ: " + mqEx.ToString());
}
}
catch (Exception e)
{
logger.Error("Exception while peeking into MSMQ: " + e.ToString());
}
if (currentMessage != null)
{
logger.Info(currentMessage.Body.ToString());
try
{
ProcessMessage(currentMessage);
}
catch (Exception processMessageException)
{
logger.Error("Error in process message: " + processMessageException.ToString());
}
//Remove message from queue.
logger.Info("Message removed from queue.");
q.Receive();
//logPerformance(ref transCount, ref startTime);
}
}//end while
Thread.CurrentThread.Abort();
}
Dzięki za odpowiedź: - w odniesieniu do warunków wyścigu: Nie jestem pewien, czy widzę warunki wyścigu, o których wspomniałeś. Według http://msdn.microsoft.com/en-us/library/t5te2tk0.aspx, MessageQueue.Peek (Timeout) jest wywołaniem blokującym. - Jestem zaniepokojony użyciem wzorca asynchronicznego, ponieważ ProcessMessage wykonuje niektóre operacje COM. Nie wiem, czy te operacje są bezpieczne dla wątków. Jestem w porządku z próbą użycia funkcji odbierania() zamiast wartości szczytowej, z tą różnicą, że nie wiem, jak utworzyć możliwość zatrzymania pętli while z powodu zatrzymania usługi. –
Re: COM w 'ProcessMessage': nie powinno stanowić problemu, jeśli działa tylko jeden wątek' ProcessMessage' (który można osiągnąć w przypadku asynchronizmu, uruchamiając nowy asynchroniczny odbiór po zakończeniu funkcji "ProcessMessage".) W asynchronizmie jeśli zamkniesz kolejkę (i opróżnisz pamięć podręczną --- na podstawie wyszukiwania, które wydaje się być potrzebne, aby naprawdę zamknąć połączenie) i wszystkie oczekujące otrzymane zostaną anulowane.Nie ma pętli do anulowania.Nie ma pętli do anulowania – Richard