所以我有UI在我的应用程序中创建日历事件。创建新事件时,我会为所有用户创建通知(大约3,000个)。我需要一段时间,因为我需要为每个用户写入数据库来创建他们的通知,所以我创建了一个继承自BackgroundWorker
的类。我真的不在乎是否创建了通知(我这样做,但不是在为最终用户完成请求的上下文中),所以我认为这将是一种有效的方法。
当我去实现它时,即使在调用context.Response.End()
之后,HttpHandler
仍然等待后台工作者完成。我调试了线程,HttpHandler
和BackgroundWorker
有不同的线程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
...
}
}
}
任何见解都会很棒。提前一堆谢谢!
答案 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()
}