Как работать с HttpTaskAsyncHandler



public class FooHandler  : HttpTaskAsyncHandler
{
public override async Task ProcessRequestAsync(HttpContext context)
{
return await new AdRequest().ProcessRequest();
// getting error here. "Return type of async type is void"
}
}

public class FooRequest
{

public async Task<String> ProcessRequest()
{
//return await "foo"; obviously nothing to wait here
}

}


Я хочу сделать асинхронный обработчик и просто хочу вернуть строку. Как я могу заставить это работать? и есть ли краткое указание на работу с асинхронными методами и задачами?

541   3  

3 ответов:

Несколько пунктов:

  • Вы можете await любые Task, а не только те, которые возвращаются из методов async.
  • Методы async оборачивают возвращаемое значение в Task<TResult>; если возвращаемое значение отсутствует, они оборачивают само возвращение в Task.
  • есть несколько доступных методов удобства, например, Task.FromResult, Если вам не нужны накладные расходы метода async.
  • только сделайте метод async, Если вам нужно использовать await в нем. Если вам не нужно делать метод async, не надо.

Мой асинхронный/ждут интро полезная.

public class FooHandler  : HttpTaskAsyncHandler
{
  public override Task ProcessRequestAsync(HttpContext context)
  {
    return new AdRequest().ProcessRequest();
  }
}

public class AdRequest
{
  public Task<String> ProcessRequest()
  {
    return Task.FromResult("foo");
  }
}

Вы не должны "возвращать" задачу, компилятор сделает это неявно, так как это асинхронная функция:

public override async Task ProcessRequestAsync(HttpContext context)
{
    await new AdRequest().ProcessRequest();
}

public async Task<String> ProcessRequest()
{
    return "foo";
}

Это другой способ, более близкий к тому, что вы пытались сделать: (без async / await)

public override Task ProcessRequestAsync(HttpContext context)
{
    return new AdRequest().ProcessRequest();
}

public Task<String> ProcessRequest()
{
    return Task.Return("foo");
}

Общая ссылка на async является здесь По существу, добавление модификатора async к методу делает его возвращающим Task неявно. Если вы вернете int, он превратит его в Task<int>. await делает обратное, превращая Task<int> в int.

Это действительно асинхронный метод:

public Task<string> ProcessRequest()
{
    var textFile = File.OpenText("file.txt");
    var readTask = textFile.ReadToEndAsync();

    readTask.ContinueWith(previousTask => textFile.Dispose());

    return readTask;
}

Если вы запускаете этот метод с большим файлом или файлом на медленном диске, выполнение вернется к вызывающему задолго до окончания чтения файла. В Примере Стивена Клири вызывающий получит обратно контроль только тогда, когда результат ("foo") будет закончен вычислением.

Dispose должен быть в ContinueWith, потому что выполнение метода вернется к вызывающему до завершения чтения файла, поэтому файл не может быть закрыт в ProcessRequest метод.

Можно, конечно, начать свою собственную задачу.

public Task<string> ProcessRequest(CancellationToken cancellationToken)
{
    var readTask = Task.Run(() =>
    {
        using (var textFile = File.OpenText("file.txt"))
        {
            var text = textFile.ReadToEnd();

            cancellationToken.ThrowIfCancellationRequested();

            var processedText = text.Replace("foo", "bar");

            return processedText;
        }
    });

    return readTask;
}

Хорошей практикой является иметь CancellationToken и периодически проверять, была ли запрошена отмена, чтобы разрешить отмену длительных операций.

Правка 1

As @Stephen Cleary выделил первый образец, и это приводит к приблизительно или, возможно, точно такому же CIL:

public async Task<string> ProcessRequest()
{
    using (var textFile = File.OpenText("file.txt"))
    {
        var s = await textFile.ReadToEndAsync();

        return s;
    }
}

В основном компилятор преобразует код, следующий за текстовым файлом await.ReadToEndAsync () в Продолжайте.

Каждый синтаксис имеет свои преимущества, я предпочитаю, чтобы 1-2 строки (т. е. dispose и log) шли в ContinueWith, более сложные продолжения используют await.

Comments

    Ничего не найдено.