24

我正在尝试使用新的异步 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");
            });
        }

但随后神秘地得到这个编译器错误:由于这是一个异步方法,返回表达式必须是“字符串”类型而不是Task<string>

我在这里想念什么?

4

2 回答 2

20

您可能想阅读我的async/await介绍文章

方法的返回值async包装在Task<TResult>. 同样,await解开这些返回值:

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

这背后的原因在我的异步“为什么关键字以这种方式工作”非官方常见问题解答中进行了描述。

PS您也可以Task.FromResult用于这样的简单测试。

编辑:如果你想创建并返回Task对象本身,那么方法应该是async. 一种比较常见的模式是有一个public非方法,仅在必要时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;
}
于 2012-07-30T01:25:20.313 回答
3

“任务方法”也可以是“异步”方法吗?

是的,只需将方法签名更改为public async static Task<Task<String>> LongTaskAAsync()它将返回的内容即可。

如果您使用async关键字,运行时会将您返回的类型包装到任务中,以启用异步。假设您返回 a string,运行时会将其包装到 aTask<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");
    }
}
于 2012-07-30T01:23:07.720 回答