4

そのため、アプリ内でカレンダー イベントを作成するための UI があります。新しいイベントが作成されると、すべてのユーザー (約 3,000) に対して通知を作成します。各ユーザーが通知を作成するためにデータベースに書き込む必要があるため、これにはしばらく時間がかかります。そのため、から継承するクラスを作成しましたBackgroundWorker。通知が作成されるかどうかはあまり気にしません (作成しますが、エンド ユーザーの要求を完了するというコンテキストではありません) ので、これは有効なアプローチだと思いました。

しかし、私がそれを実装しようとしたとき、 を呼び出した後でもcontext.Response.End()HttpHandlerまだバックグラウンド ワーカーが終了するのを待っています。スレッドをデバッグし、異なるスレッド IDHttpHandlerを持っています。BackgroundWorkerどういうわけか戻ってくるのを黒くしているのか、それともクラスの目的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 に答える