IHttpAsyncHandler не выполняется асинхронно

Я работаю с существующей кодовой базой внешнего интерфейса Silverlight и коллекцией внутренних классов IHttpHandler. У меня возникла ситуация, когда мне нужно связать клиента и дождаться завершения действия на стороннем сайте, а затем перезвонить на наш сайт и сказать, что "ожидаемое действие завершено", чтобы клиент мог продолжить.

Основной поток:

  1. Клиент направляет пользователя на сторонний сайт в новой вкладке
  2. Клиент вызывает серверный класс для ожидания обновления статуса в базе данных
  3. Пользователь выполняет действие на стороннем сайте, сторонний сайт перенаправляет на страницу на нашем сайте
  4. Страница из #3 отмечает действие как выполненное в базе данных
  5. Класс из #2 видит статус "завершен", возвращается к клиенту
  6. Клиент продолжает как обычно

У меня нет большого контроля над этим процессом; без существенных изменений в существующем коде, это более или менее то, как этот процесс должен происходить.

При тестировании этого я обнаружил, что хотя вызов #2 происходит асинхронно в клиенте, сервер все еще связан в ожидании обновления статуса (я не слишком знаком с IHttpHandlers; я узнал это неделю, что они синхронны) и другие звонки на сервер не проходят

Чтобы исправить это, я пытаюсь сделать вызов в #2 асинхронным путем реализации IHttpAsyncHandler:

public abstract class BaseControl_Asynchronous : BaseControl, IHttpAsyncHandler
{
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
    {
        this.Context = context;
        this.Login = Utils.IsNullOrEmpty(Context.Session["Login"] as string, string.Empty);
        this.Domain = Utils.IsNullOrEmpty(Context.Session["Domain"] as string, "Demo");
        this.Init();

        var processRequestAsync = this.ProcessRequestAsync(context);
        var completionSource = new TaskCompletionSource<object>(context);

        processRequestAsync.ContinueWith((t, o) =>
        {
            if (t.IsFaulted)

            {
                if (t.Exception != null)
                {
                    completionSource.SetException(t.Exception.InnerExceptions);
                }
            }
            else
            {
                completionSource.SetResult(null);
            }

            cb(completionSource.Task);
        }, extraData);

        return completionSource.Task;
    }

    private async Task ProcessRequestAsync(HttpContext context)
    {
        await Task.Run(() => this.ProcessRequest_Internal(context));
    }

    public void EndProcessRequest(IAsyncResult result)
    {
        ((Task)result).Wait();
    }

    public void ProcessRequest(HttpContext context)
    {
        throw new InvalidOperationException();
    }
}

BaseControl - это существующий базовый класс для существующей коллекции классов IHttpHandler. Я разделил это на BaseControl_Synchronous и BaseControl_Asynchronous (см. Выше) и BaseControl, который содержит общий код для них обоих.

Вот базовая реализация ProcessRequest_Internal (в BaseControl):

public virtual void ProcessRequest_Internal(HttpContext context)
    {
        string output = string.Empty;

        // output contains a response envelope, code to construct envelope skeleton removed

        // abstract method implemented by sub classes
        string result = Execute();

        // code that appends result to response envelope removed

        context.Response.ContentType = ContentType;
        context.Response.Output.Write(output);
    }

В моем случае код "Выполнить" ожидает обновления этого статуса в базе данных. Я бы подумал из-за кода в BaseControl_Asynchronous, что этот подход будет работать, но код, который ожидает обновления состояния, связывает сервер, и никакие другие вызовы не выполняются, пока он ожидает.

Это просто неправильный подход? Я пытаюсь оставить как можно больше кода (я не хочу так сильно изменять ProcessRequest_Internal, слишком много унаследованного кода зависит от него), но я готов полностью разделить эти два процесса, если есть нет способа повторно использовать этот метод.

Есть идеи? Заранее спасибо!

0 ответов

Другие вопросы по тегам