Вопрос по asynchronous, nancy, asp.net, async-await, c#-5.0 – Как я могу вызвать асинхронный процесс из размещенного модуля asp.net, используя C # 5 async / await?

0

У меня есть длительный процесс, который вызывается с помощью метода Get модуля Nancy. Вместо того, чтобы браузер зависал во время работы процесса, я хотел бы, чтобы этот вызов был асинхронным, другими словами, я хочу, чтобы метод Get сразу возвращался и оставлял длительно работающий процесс на свое место. Затем я мог бы регулярно проверять состояние процесса и действовать соответствующим образом.

Я новичок в асинхронных / ожидающих функциях C # 5, но я уверен, что они предназначены именно для такого рода задач. Код ниже показывает мою попытку. Я вставил некоторые записи, которые демонстрируют, что он не работает асинхронно, как ожидалось. Вместо этого длительный процесс блокирует метод Get и браузер зависает.

Module

public class TestModule : NancyModule
{            
    public TestModule(ITestService testService)
    {
        Get["/longprocess"] = _ =>
            {
                Log.Write("Module : Start");
                testService.LongProcess();
                Log.Write("Module : Finish");
                return HttpStatusCode.OK;
            };
    }
}

Service

public interface ITestService
{
    Task<bool> LongProcess();
}

public class TestService : ITestService
{
    public async Task<bool> LongProcess()
    {
        await LongProcessAsynch();
        return true;
    }

    private Task<bool> LongProcessAsynch()
    {
        Log.Write("LongProcess : Start");
        Thread.Sleep(5000);
        //Task.Delay(5000); <- Has same effect
        Log.Write("LongProcess : Finish");
        return true.AsTask();
    }
}

Extension Method

public static Task<T> AsTask<T>(this T candidate)
{
    var source = new TaskCompletionSource<T>();
    source.SetResult(candidate);
    return source.Task;
}

Log Output

14/06/2012 19:22:29 : Module : Start
14/06/2012 19:22:29 : LongProcess : Start
14/06/2012 19:22:34 : LongProcess : Finish
14/06/2012 19:22:34 : Module : Finish

Вы можете видеть из выхода журнала выше, чтоLongProcess() блокирует возврат модуля Get. Если бы задача выполнялась асинхронно, я бы ожидал, что журнал будет выглядеть примерно так:

Expected Log

Module : Start
LongProcess : Start
Module : Finish
LongProcess : Finish

Я думаю, что на самом деле требуется поставитьawait в методе Get NancyModule. Возможно, что-то вроде приведенного ниже кода, но я не могу сделать это, потому что я не могу пометить конструктор модуля какasnyc и поэтому я не могу использоватьawait в методе Get (или так в настоящее время я верю)

Get["/longprocess"] = _ =>
    {
        Log.Write("Module : Start");
        await testService.LongProcess();
        Log.Write("Module : Finish");
        return HttpStatusCode.OK;
    }; 

Спасибо за любую помощь, примеры или указатели на ресурсы.

Edit 1

Дополнительные исследования показывают, что asp.net активно предотвращаетasync звонки по умолчанию. Что-то делать сSession и то, как он обрабатывает не потоки пользовательского интерфейса, я верю. Поэтому я добавил следующее в мой web.config (см. Ниже)

UseTaskFriendlySynchronizationContext enableSessionState="false"

К сожалению, это не имеет никакого значения, и мойasync / await позвонитьLongProcess() все еще блокирует

<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    <add key="webPages:Enabled" value="false" />
  </appSettings>
  <system.web>
    <httpRuntime targetFramework="4.5"/>
    <pages controlRenderingCompatibilityVersion="4.0" enableSessionState="false" />
    ... more config
</configuration>
Я не знаю, что такое NancyFX, но он должен поддерживать Задачи в качестве возвращаемых значений, чтобы вы могли использовать его асинхронно. usr
Я вложил асинхронный вызов, чтобы попытаться обойти это. Первоначальный вызовtestService.LongProcess() синхронно, но это тогда вызываетLongProcessAsynch() метод с использованиемawait Ключевое слово и поэтому это должно быть асинхронным. Вы считаете это правильным? biofractal

Ваш Ответ

2   ответа
1

e meant for just this kind of task.

Нет.async/await предназначены для облегчения асинхронного программированияwithin the context of a single process, Они не меняют природу HTTP-коммуникаций.

Когда вы используетеawait на сервере ASP.NET (в контексте HTTP-запроса) вы возвращаете поток ASP.NET в пул потоков. Однако ASP.NET знает, что HTTP-запрос не завершен, поэтому он не завершает ответ клиенту (браузеру).

Это по замыслу.

Вам нужно использовать AJAX, SignalR или другое решение, чтобы делать то, что вы хотите.

В настоящее время я использую jQuery $ .ajax (), чтобы сделать мой асинхронный вызов для моего API. Конечно, это не совсем асинхронно, поскольку asp.net блокирует ответ, как вы описываете. Так что мой единственный вариант - раскрутить новый поток и вернуть идентификатор? Это, безусловно, сработает, но я хочу дважды проверить, что я не могу использовать новые функции асинхронной передачи, учитывая атрибут configUseTaskFriendlySynchronizationContext? Извините, что повторяю мой вопрос, но я хочу быть уверенным, прежде чем я уйду и займусь решением старой проблемы. biofractal
Хорошо, я согласен с тем, что я лаю не на том дереве, поэтому внимательно посмотрю на то, чего я пытаюсь достичь, и посмотрим, можно ли это сделать с помощью более простого подхода. Спасибо за совет. biofractal
Вы не хотите раскручивать новый поток (это почти всегда ошибка в ASP.NET; подумайте об утилизации). Сделайте шаг назад и изучите ваши требования. Вы хотите выполнить команду, которая запустит рабочий процесс. Веб-серверы не были предназначены для этого; вам действительно нужно как-то сохранить его (например, MSMQ / Azure Queues) или передать его другому серверу (например, службе Win32).
0

попробуйте установить атрибут страницыAsync="true"in the aspx page after doing that it wold look like this <%@ Page Language="C#" AutoEventWireup="true" CodeFile="XXX.aspx.cs" Inherits="xxx" Async="true" %>

в файле Tcode behile вы можете сделать задачи и методы типа async и calllawait  задачи от них ...

это может сработать

Похожие вопросы