简体   繁体   中英

How to use yield in async C# task

I am trying to you use yield and return a result from converting X into Y in an async task. But, I am getting an error on select. The error is:

Error CS1942 The type of the expression in the select clause is incorrect. Type inference failed in the call to 'Select'.

public async Task<Result<dynamic>> GetYAsync(IEnumerable<X> infos)
    {
        return Task.WhenAll(from info in infos.ToArray() select async ()=>
        {
            yield return await new Y(info.Id, "Start");
        });
    }

Short answer: you can't use an asynchronous yield statement.

But in most cases, you don't need to. Using LINQ you can aggregate all tasks before passing them into Task.WaitAll . I simplified your example to return an IEnumberable<int> , but this will work with every type.

public class Program
{
   public static Task<int> X(int x) {
      return Task.FromResult(x);
   }

   public static async Task<IEnumerable<int>> GetYAsync(IEnumerable<int> infos)
   {
      var res = await Task.WhenAll(infos.Select(info => X(info)));
      return res;
   }

   public static async void Main()
   {
      var test = await GetYAsync(new [] {1, 2, 3});
      Console.WriteLine(test)   ;
   }
}

Your example has another error await new Y(...) , a constructor cannot be asynchronous, therefore I replaced it with an asynchronous function. (As hinted in the comments, it is technically possible to create a custom awaitable type and create this type with new , although this is rarely used),

The example above uses infos.Select to create a list of pending tasks, returned by invoking the function X . This list of tasks will then be awaited and returned.

This workaround should fit most cases. Real asynchronous iterators, as for example in JavaScript, are not supported in .Net.

Update: This feature is currently suggested as a language proposal: Async Streams . So maybe we will see this in the future.

Update: If you need asynchronous iterators, there are a few options currently available:

  1. Reactive Stream, RX.Net , which provides you with asynchronous observable streams based on events.
  2. There are implementations of asynchronous iterators or asynchronous enumerables AsyncEnumerable or .Net Async Enumerable

You do not. Async Enum support (and yield is there to implement enumerable) comes with C# 8 some point in 2019 as it looks. So, for now the answer is simply that you do not.

The reason you get the error is that you can also not returna Result. Yield (return) is specific to implementing enumerations. Your method signature does not match.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM