Подтвердить что ты не робот

С# Может ли "метод задачи" также быть "асинхронным" методом?

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

    public static Task<String> LongTaskAAsync() {
        return Task.Run(() => {
            return("AAA");
            });
        }

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

public async static Task<String> LongTaskAAsync() {
        await Task.Delay(2000);
        return Task.Run(() => {
            return("AAA");
            });
        }

Но тогда таинственно получаю эту ошибку компилятора: поскольку это асинхронный метод, возвращаемое выражение должно иметь тип 'string', а не Task<string>

Что мне здесь не хватает?

4b9b3361

Ответ 1

Возможно, вы захотите прочитать мой async/await пост вступления.

Возвращаемые значения из методов async заключены в Task<TResult>. Аналогично, await разворачивает возвращаемые значения:

public static async Task<String> LongTaskAAsync() {
  await Task.Delay(2000);
  return await Task.Run(() => {
    return("AAA");
  });
}

Обоснование этого описано в моей Async "Почему так работают ключевые слова" Неофициальный FAQ.

P.S. Вы также можете использовать Task.FromResult для простых тестов, подобных этому.

Изменить: Если вы хотите создать и вернуть сам объект Task, то метод не должен быть async. Одним из наиболее распространенных шаблонов является метод public non async, который вызывает только часть async.

Например, какой-то асинхронный кеш - если объект находится в кеше, то немедленно возвращайте его; в противном случае, асинхронно создайте его, добавьте в кэш и верните его (это пример кода, а не потокобезопасный):

public static Task<MyClass> GetAsync(int key)
{
  if (cache.Contains(key))
    return Task.FromResult(cache[key]);
  return CreateAndAddAsync(key);
}

private static async Task<MyClass> CreateAndAddAsync(int key)
{
  var result = await CreateAsync(key);
  cache.Add(key, result);
  return result;
}

Ответ 2

Может ли "метод задачи" также быть "асинхронным" методом?

Да, это может быть, просто изменив подпись метода на public async static Task<Task<String>> LongTaskAAsync(), так как это то, что он вернет.

Если вы используете ключевое слово async, среда выполнения вернет тип, возвращаемый в задачу, чтобы включить асинхронность. Скажем, если вы вернете string, среда выполнения перенесет это в Task<string>. int пойдет Task<int>, а Task<string> пойдет Task<Task<string>>. См. Это консольное приложение для очистки:

public class Program
{
    public static void Main(string[] args)
    {
        // start the main procedure asynchron
        Task.Run(() => DoIt()).Wait();
    }

    // for async support since the static main method can't be async
    public static async void DoIt()
    {
        Program p = new Program();

        // use the methods
        string s = await p.GetString();
        int i = await p.GetInt();
        Task<string> tsk = await p.GetTaskOfString();

        // just to prove the task works:

        // C# 5
        string resultFromReturnedTask = await tsk;

        // C# 4
        string resultFromReturnedTask2 = tsk.Result;
    }

    public async Task<string> GetString()
    {
        return "string";
    }

    public async Task<int> GetInt()
    {
        return 6;
    }

    public async Task<Task<string>> GetTaskOfString()
    {
        return Task.Run(() => "string");
    }
}