从AsyncController中的MSMQ返回null值的方法

时间:2012-11-25 20:50:43

标签: asp.net-mvc delegates 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();

但我最终遇到编译错误,告诉我返回类型是无效的。

不可否认,我对代表们来说仍然很陌生,但我非常感谢你们朝着正确的方向前进。

谢谢 -


编辑11/25/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 个答案:

答案 0 :(得分:0)

如编辑原始问题所述,我发现毕竟我不需要代表:

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客户端进入发布阶段。