So I have UI to create a calendar event within my app. When a new event is created I create notifications for all my users (around 3,000). I new this would take a while because I need to write to the database for each user to create their notification, so I created a class that inherits from BackgroundWorker. I don’t really care if the notifications are created (I do, but not in the context of getting the request finished for the end user) so I thought this would be a valid approach.
When I went to implement it however, even after calling context.Response.End(), the HttpHandler still waits for the background worker to finish. I debugged the threads and HttpHandler and BackgroundWorker have different thread ids. I am not sure if I am somehow blacking the HttpHandler from returning or if I misunderstood what the BackgroundWorker class is for.
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
...
}
}
}
Any insight would be awesome. Thanks a bunch in advance!
BackgroundWorkerintegrates with the currentSynchronizationContext. It has been designed in such a way that it doesn’t let the current request end before theBackgroundWorkeris finished. This is what you want most of the time.I suggest you queue your work item to the thread-pool by starting a new
Task.