Метод, возвращающий нулевое значение из MSMQ в AsyncController

Я пытаюсь создать основу для доставки сообщений в режиме реального времени (используя MSMQ на данный момент) для отображения на веб-странице, которая будет служить информационным дисплеем. Как только сообщение попадет в очередь, я бы хотел, чтобы сообщение отображалось на странице.

контроллер:

public class MessageController : AsyncController
{
    public void IndexAsync()
    {
        AsyncManager.OutstandingOperations.Increment(1);
        Task<string>.Factory.StartNew(() =>
            {
                var queue = new MessageQueue(@".\private$\path-to-queue");
                while (true)
                {
                    var message = string.Empty;
                    var result = queue.BeginReceive();
                    queue.Formatter = new XmlMessageFormatter(new[] {typeof (string)});
                    queue.ReceiveCompleted += delegate(object sender, ReceiveCompletedEventArgs args) { message = args.Message.Body.ToString(); };
                    queue.EndReceive(result);
                    return message;
                }
            }).ContinueWith(t =>
                {
                    AsyncManager.Parameters["message"] = t.Result;
                    AsyncManager.OutstandingOperations.Decrement();
                }
            );
    }

    public JsonResult IndexCompleted(string message)
    {
        return Json(message, JsonRequestBehavior.AllowGet);
    }
}

Когда я вызываю действие из браузера, браузер ожидает появления сообщения в очереди. Когда я добавляю сообщение в очередь, браузер продолжает запрос, но в итоге я получаю пустую строку вместо содержимого сообщения.

Альтернативно, я попытался заменить

message = args.Message.Body.ToString();

в делегате с

return args.Message.Body.ToString();

но я закончил с ошибкой компилятора, говорящей мне, что возвращаемый тип void.

Следует признать, что я все еще новичок в делегатах, но я был бы очень признателен за продвижение в правильном направлении.

Спасибо--


Изменить 25.11.2012 @ 22:29

Я пришел к рабочему решению... не уверен, что это лучший метод, поэтому я оставляю это открытым для некоторой экспертной оценки.

public class MessageController : AsyncController
{
    public void IndexAsync()
    {
        AsyncManager.OutstandingOperations.Increment(1);
        Task<Message>.Factory.StartNew(() =>
            {
                var queue = new MessageQueue(@".\private$\path-to-queue");
                while (true)
                {
                    var result = queue.BeginReceive();
                    queue.Formatter = new XmlMessageFormatter(new[] {typeof (string)});
                    var message = queue.EndReceive(result);
                    return message;
                }
            }).ContinueWith(t =>
                {
                    AsyncManager.Parameters["message"] = t.Result.Body.ToString();
                    AsyncManager.OutstandingOperations.Decrement();
                }
            );
    }

    public JsonResult IndexCompleted(string message)
    {
        return Json(message, JsonRequestBehavior.AllowGet);
    }
}

1 ответ

Решение

Как указано в редактировании исходного вопроса, я обнаружил, что мне в конце концов не нужен делегат:

public class MessageController : AsyncController
{
    public void IndexAsync()
    {
        AsyncManager.OutstandingOperations.Increment(1);
        Task<Message>.Factory.StartNew(() =>
            {
                var queue = new MessageQueue(@".\private$\path-to-queue");
                while (true)
                {
                    var result = queue.BeginReceive();
                    queue.Formatter = new XmlMessageFormatter(new[] {typeof (string)});
                    var message = queue.EndReceive(result);
                    return message;
                }
            }).ContinueWith(t =>
                {
                    AsyncManager.Parameters["message"] = t.Result.Body.ToString();
                    AsyncManager.OutstandingOperations.Decrement();
                }
            );
    }

    public JsonResult IndexCompleted(string message)
    {
        return Json(message, JsonRequestBehavior.AllowGet);
    }
}

Хотя я отмечу одну вещь... Я не учел, что будет несколько экземпляров контроллера, опрашивающего очередь на наличие сообщений, поэтому вы в конечном итоге столкнетесь с ситуацией, когда сеансы браузера конкурируют за сообщения. Один браузер получит первое сообщение, другой браузер получит второе и т. Д. Я закончил тем, что переключил эту реализацию на SignalR- просто ожидал перехода клиента.NET в фазу выпуска.

Другие вопросы по тегам