实现异步控制器操作时的问题和错误

时间:2015-09-08 08:53:15

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

似乎我在理解有关C#中的异步操作以及控制器中的ASP.NET MVC这一主题时遇到了大量问题。

我的网页上的所有 AJAX-Requests 都有控制器。每个我都有一个动作。现在我尝试像'通知系统'那样实现。我创建了一个处理队列中通知的类,它通过使用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),消息:&gt;&gt;此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动。如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async="true" %>。此异常还可能表示尝试调用“异步void”方法,该方法通常在ASP.NET请求处理中不受支持。相反,异步方法应该返回一个Task,调用者应该等待它。&lt;&lt;

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

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

我的问题是以上以及如何解决问题。有没有更好的解决方案,什么时候可以实现?

我感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

请勿使用async void,而是使用async Taskasync void操作通常会被解雇,因为您无法异步等待它们。此外,使用AsyncController时无需使用async-await。您可以阅读有关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这样的技术,这甚至可以非常简单和友好。我建议调查一下。