使用Nancy Async Beta进行长时间轮询

时间:2013-04-15 23:56:37

标签: c# async-await long-polling nancy

通常我会使用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上找到的documentation,看起来这个例子应该可行......但不是 - 对我来说无论如何。如果有人能够提供一些有关为什么不起作用的见解,那将非常感激。就像我说的那样,我可以发布更多来自这个实验的代码,但是现在它似乎只会让问题变得混乱。

更新 由于我对TPL和南希相对较新,我已经将我的代码从实验中删除,以便隔离问题并排除故障。这是我更新的代码。它只是等待5秒的任务延迟,然后将当前时间发送给客户端。

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

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

async illustration

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

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

1 个答案:

答案 0 :(得分: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);
            });