1

我正在尝试构建一个用于实时传递消息的框架(目前使用 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();

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

诚然,我对代表们还是很陌生,但我非常感谢朝着正确的方向前进。

谢谢 -


编辑 2012 年 11 月 25 日 @ 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);
    }
}
4

1 回答 1

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

于 2012-11-26T16:14:01.993 回答