6

通常我会使用 SignalR 来处理任何数据推送,但在这种情况下,我在服务器端使用 Nancy Async Beta 的自托管实例。我听说在这种情况下仍然可以使用 SignalR,但在这种情况下我仍然更愿意自己处理长轮询。这是我正在编写的一个简单实验应用程序的代码,它会产生如下所述的问题:

        Get["/receivechat", true] = async (x, ct) =>
            {
                string result = await _massPublisher.WaitForResult("test");
                return result;
            };

这处理实际的长轮询请求。请求似乎以 4 或 5 个块的形式输入此 lambda。例如,如果我在 lambda 的第一行放置一个断点,我不会看到断点被击中,直到我再发送 4 或 5 个请求然后突然所有请求一次全部进入 lambda。显然,我需要他们按照要求全部输入,以便他们都可以等待我的 WaitForResult 方法。WaitForResult 方法只是等待一个普通的TaskCompletionSource。如有必要,我可以发布该代码和客户端代码。据我所知,这似乎是我如何使用 Nancy Async Beta 的问题,因为请求是并行处理的,并且在发出其他一些请求之前,请求甚至不会进入 lambda。

值得注意的是,此应用程序在此期间仍响应所有其他请求。

我已经阅读了我可以在 Nancy Async Beta 上找到的文档,看起来这个示例应该可以工作......但它不是 - 无论如何对我来说。如果有人可以就为什么这不起作用提供一些见解,将不胜感激。就像我说的那样,我可以从这个实验中发布更多代码,但现在看来它只会让问题变得混乱。

更新: 由于我对 TPL 和 Nancy 比较陌生,因此我已将我的代码从实验中取出,以便隔离问题并进行更多故障排除。这是我更新的代码。它只是等待 5 秒的任务延迟,然后将当前时间发送给客户端。

        Get["/receivechat", true] = async (x, ct) =>
            {
                //string result = await _massPublisher.WaitForResult("test");
                //return result;
                await Task.Delay(5000);
                return DateTime.Now.ToString();
            };

我的理解是每个请求都将并行处理并且彼此独立。现在有了这种理解,我认为每个客户端应该每 5 秒看到一次回复,无论有多少其他客户端正在轮询这些请求。但是,结果如下:

异步插图

换句话说,每 5 秒发送一次响应,但一次只发送给一个客户端。因此,对于 3 个客户端,每个客户端需要 15 秒才能收到其响应。对于 2 = 10 秒等...

到目前为止,我看不出我做错了什么。这就是我在这里的原因。我喜欢发现我错了!:) 我会学到一些新东西。因此,如果您知道或可能知道我哪里出错了,请告诉我。我可能错过了一些我在多次寻找时忽略的小而愚蠢的东西,希望这是一个其他人会发现有用的错误。

4

1 回答 1

7

在 Steven Robbins 非常感谢的帮助下找出了问题所在。这是浏览器一次不发送多个待处理请求,但我之前已经在所有浏览器(包括我用来测试的 Chrome)上看到了这项工作。浏览器将与服务器建立多个并发连接,但这些请求必须是唯一的(显然)。如果 Chrome 看到与即将发送的请求完全匹配的待处理请求,它将等待待处理请求完成,从而导致问题中所示的确切输出,因为其他客户端是同一浏览器的更多窗口(请参见问题中的图像和说明)。

因此,通过将 JS 的注释行(下面)更改为上面的行(主要是为了解决缓存问题),它也解决了长轮询问题,突然我在问题中的两个示例都很好用。

            $.get("/receivechat?_=" + new Date().getTime(), null, function (data)
            //$.get("/receivechat", null, function (data)
            {
                self.viewModel.chatLines.push(data);
                self.update();
            }).error(function ()
            {
                setTimeout(self.update, 2000);
            });
于 2013-04-18T15:38:25.820 回答