4

所以我有 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
            ...
        }
     }
}

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

4

2 回答 2

5

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

我建议您通过启动一个新的Task.

于 2012-09-16T19:14:18.867 回答
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()
    }
于 2012-09-16T18:42:58.247 回答