BackgroundWorker仍然阻止IHttpHandler

时间:2012-09-16 14:22:26

标签: c# asp.net sql-server

所以我有UI在我的应用程序中创建日历事件。创建新事件时,我会为所有用户创建通知(大约3,000个)。我需要一段时间,因为我需要为每个用户写入数据库来创建他们的通知,所以我创建了一个继承自BackgroundWorker的类。我真的不在乎是否创建了通知(我这样做,但不是在为最终用户完成请求的上下文中),所以我认为这将是一种有效的方法。

当我去实现它时,即使在调用context.Response.End()之后,HttpHandler仍然等待后台工作者完成。我调试了线程,HttpHandlerBackgroundWorker有不同的线程ID。我不确定我是否以某种方式使HttpHandler无法返回,或者如果我误解了BackgroundWorker类的用途。

class EventHandler : IHttpHandler
{
    ...
    public void ProcessRequest(HttpContext context)
    {
         ...
         // I need this to finish before the response ends
         CalendarEvent event = CreateCalendarEvent();
         List<int> users = GetUsersFromDB();
         if(event != null) // The event was created successfully so create the notifications
         {
             // This may take a while and does not effect the UI on
             // client side, so it can run in the background
             NotificationBackgroundWorker notificationWorker = new NotificationBackgroundWorker(notification, users);
             notificationWorker.RunWorkerAsync();
         } else {
            ...
            // Log Error and set status code for response
            ...
         }
         ...
         context.Response.End()
    }
    ...
}

class NotificationBackgroundWorker : BackgroundWorker
{
    private Notification notification;
    private List<int> users;

    public NotificationBackgroundWorker(Notification newNotification, List<int> usersToNotify) : base()
    {
        this.notification = newNotification;
        this.users = usersToNotify;
        this.DoWork += DoNotificationWork;
    }

    private void DoNotificationWork(object sender, DoWorkEventArgs args)
    {
        CreateUserNotifications(notification, users);
    }

    private void CreateUserNotifications(Notification notification, List<int> userList)
    {
        // This is where the bottleneck is occurring because there 
        // is one DB write per user
        foreach (int userId in userList)
        {
            ...
            // Create the notification for each user
            ...
        }
     }
}

任何见解都会很棒。提前一堆谢谢!

2 个答案:

答案 0 :(得分:5)

BackgroundWorker与当前SynchronizationContext集成。它的设计方式使它不会让当前请求在BackgroundWorker完成之前结束。这是你大多数时候想要的。

我建议您通过启动新的Task将工作项排入线程池。

答案 1 :(得分:1)

在另一个线程中执行,而不是使用BackgroundWorker。我不确定BackGroudWorker是否会在这种情况下工作。

public void ProcessRequest(HttpContext context)
    {
         ...
       // I need this to finish before the response ends
       CalendarEvent event = CreateCalendarEvent();
       List<int> users = GetUsersFromDB();
       if(event != null) // The event was created successfully so create the notifications
       {

             Thread thread = new Thread(
            () =>
             {
                CreateUserNotifications(notification, users);
             });
             thread .IsBackground = true;
            thread.Start();

       } else {
            ...
            // Log Error and set status code for response
            ...
         }
         ...
         context.Response.End()
    }