Метод, возвращающий нулевое значение из 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 в фазу выпуска.