MSMQ — Получение завершено — Асинхронная обработка сообщений

#c# #asynchronous #async-await #msmq

#c# #асинхронный #асинхронный -ожидание #msmq

Вопрос:

Я использую метод BeginnReceive и обработчик событий ReceiveCompleted для прослушивания и обработки сообщений из MSMQ.

Я поместил метод BeginReceive в начало обработчика событий ReceiveCompleted.

Похоже, в моем консольном приложении все работает нормально. Прямо сейчас сообщения обрабатываются асинхронно.

Вопрос: Безопасно ли это с точки зрения потокобезопасности?
Все примеры, которые я видел, помещают вызов BeginReceive в конец завершенного обработчика событий. Итак, я спрашиваю себя, есть ли какие-либо проблемы при размещении его в самом начале завершенного обработчика?

 private void InitializeQueue()
{
    try
    {
        _mq = MessageQueue.GetPrivateQueuesByMachine(_queueServerName).Where(qu => qu.Path == _queueAddress).FirstOrDefault();
        _mq.Formatter = new BinaryMessageFormatter();
        _mq.ReceiveCompleted  = MessageReceiveCompleted;

    }
    catch (Exception ex)
    {
        Trace.WriteLine("Failed to initialize Queue!"   Environment.NewLine   " Error:"   Environment.NewLine   ex.Message);
        throw;
    }
}


async void MessageReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
    _mq.BeginReceive();
    try
    {    
        await ProcessMessageAsync(e.Message);
    }
    catch (Exception ex)
    {
        Trace.WriteLine("Error occured during report fetching:"   Environment.NewLine   ex.Message);
        throw;
    }
}
  

Комментарии:

1. Где в вашем коде многопоточный доступ, чтобы понять и оценить влияние

2. BeginReceive используется в асинхронной обработке для вызова события ReceiveCompleted, когда сообщение доступно в очереди. Я не настолько универсален, когда дело доходит до вопросов асинхронности.. поэтому я лучше спрошу, прежде чем у меня возникнут проблемы..

3. Если порядок имеет значение, я мог бы поместить BeginReceive в конец и вызвать ProcessMessageAsync с помощью Task.Run

4. Ваше понимание неверно, Async-Await зависит от портов завершения ввода-вывода механизма параллелизма на основе аппаратного обеспечения. У этого нет программных потоков, но он все еще работает одновременно в фоновом режиме. До тех пор, пока вы не создадите 3 или более Async вызовов, await для всех из которых используется Task.WhenAll , который возвращает composite Task , после запуска выполнения они будут выполняться в параллельном режиме. В вашем вставленном коде я не нахожу никаких проблем с многопоточностью, одного объекта mq , регистров для события, post notification, он выполняется BeginReceive синхронно, затем ожидает вызова веб-службы в асинхронном режиме

5. Также обратите внимание, что веб-служба является вызовом ввода-вывода, вызов через Task.Run будет мало полезен, поскольку потоки, предназначенные для обработки вычислений, будут просто ждать возврата вызова ввода-вывода. В вашем полном фрагменте кода я нигде не вижу нескольких потоков, что может вызвать проблему, такую как состояние гонки или повреждение

Ответ №1:

Да, ваш подход с помощью async / await будет безопасно обрабатывать потоки.c # асинхронный подход с этими ключевыми словами позаботится. Если быть более конкретным в моем ответе, метод обработчика событий messagereceived (имя метода должно заканчиваться на async) вызывает и ожидает асинхронный метод, если внутри этого метода есть какая-либо блокирующая работа, поток, который он приостанавливает там и выполняет дальше, пока не завершится и не вернется другая работа, как в этом случае processmessage asyncможет быть блокировка, и может быть дальнейшее выполнение вызова, но я не вижу, чтобы вы использовали это, поскольку после вызова processmessageasync вы ничего не делаете, поэтому поток будет выполнять это, если вы спросите, является ли это потокобезопасным, да, но асинхронный подход используется не полностью

Комментарии:

1. Можете ли вы объяснить, что означает этот ответ, и как он отвечает на вопрос OP

2. Пожалуйста, добавьте еще несколько деталей к вашему ответу. Сказать «Да, ваш подход будет работать» — это просто комментарий.

3. BeginRecieve прослушивается асинхронно, и каждый раз, когда поступает новое сообщение, вызывается обработчик завершения. Например, если 15 сообщений поступают подряд, все они выполняются за пару секунд. Вопрос в том, будут ли все они выполняться одним потоком, разделяемым между рабочей нагрузкой, похоже, так..