【问题标题】:Problems And Errors While Implementing Async Controller Action实现异步控制器操作时的问题和错误
【发布时间】:2015-12-03 21:01:02
【问题描述】:

似乎我在理解有关 C# 中的异步操作,尤其是控制器中的 ASP.NET MVC 的主题方面存在很大问题。

我的网页中的所有 AJAX 请求都有一个控制器。对于每一个我都有一个动作。现在我尝试像“通知系统”一样实现。我创建了一个类来处理队列中的通知,这些通知是使用 SessionID 通过字典选择的。

因为我使用的是 Reverse-AJAX,所以处理 AJAX-Response 的线程需要在服务器上保持。因此,我将Thread.Sleepwhile 结合使用来检查队列是否有元素。这是控制器的部分:

public class AJAXController : AsyncController
{
    public async void polling()
    {
        if (Session["init"] == null) //so the sessionID is not changing on every request
            Session.Add("init", 0);
        NotificationQueue queue =
                        NotificationQueue.getInstance(HttpContext.Session.SessionID);

        object responseObj = null;
        responseObj = await Task.Run(() =>
        {
            while (queue.getSize() == 0)
                Thread.Sleep(200);
            return queue.getNextQueueElement(); //behind this is queue.Dequeue();
        });
        Response.Write(new JavaScriptSerializer().Serialize(responseObj));
    }
}

基本上,我现在不知道该代码有什么不正确的地方——我知道这两个代码都不正确。

语法是正确的,但是当我尝试使用该网站时,服务器回答:500 (internal Server error),消息:>>此时无法启动异步操作。异步操作只能在异步处理程序或模块内或在页面生命周期中的某些事件期间启动。如果在执行页面时发生此异常,请确保该页面标记为<%@ Page Async="true" %>。此异常还可能表示尝试调用“async void”方法,在 ASP.NET 请求处理中通常不支持该方法。相反,异步方法应该返回一个任务,调用者应该等待它。

我需要AsyncController 吗?其他方法不是异步的,因为它们只是简单的响应。

我尝试将public async void pollingAsync()public async string pollingCompleted(string response)结合使用,但参数每次都是null

我的问题是上述以及我如何解决问题。有没有更好的解决方案,如果有,我该如何实施?

感谢您的帮助!

【问题讨论】:

  • 与您的问题没有太大关系,但这似乎是使用 SignalR 而不是 Ajax 的好用例。

标签: c# asp.net .net multithreading threadpool


【解决方案1】:

不要使用async void,而是使用async Taskasync void 操作通常是一劳永逸的,因为您无法异步等待它们。此外,在使用async-await 时,无需使用AsyncController。你可以阅读更多关于here

你需要:

public async Task PollingAsync()
{
    if (Session["init"] == null) //so the sessionID is not changing on every request
        Session.Add("init", 0);
    NotificationQueue queue =
                      NotificationQueue.getInstance(HttpContext.Session.SessionID);

    while (queue.GetSize() == 0)
        await Task.Delay(200);

    var responseObj = queue.getNextQueueElement();
    Response.Write(new JavaScriptSerializer().Serialize(responseObj));
}

一般来说,附带说明一下,您可以通过使用 websockets 来绕过“轮询”体验,使用诸如 SignalR 之类的技术,这甚至变得非常简单和友好。我建议调查一下。

【讨论】:

  • 也可能是CancellationTokenTask.Delay
  • 感谢您的回答, polling() 方法现在被调用(不像以前那样),但我得到了同样的错误。我可以试试SignalR,你能推荐任何教程或博客吗?文档似乎非常广泛,我的时间不多了..
  • @Ba5t14n 我修改了我的答案,改用Task.Delay。试试吧。
  • 好的,我几分钟前就开始工作了,现在找不到资源了。除此之外,我在该会话中遇到了巨大的性能问题,稍后尝试解决这个问题(在〜午餐后回来:))
猜你喜欢
  • 1970-01-01
  • 2014-07-27
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
相关资源
最近更新 更多