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 IEnumerable<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:
Reactive Stream, RX.Net, which provides you with asynchronous observable streams based on events.
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.
Related
I'm doing a benchmark on Task<T> and ValueTask<T>. Source code below:
#LINQPad optimize+ // Enable compiler optimizations
void Main()
{
Util.AutoScrollResults = true;
BenchmarkRunner.Run<TaskAndValueTaskComparsion>();
}
[ShortRunJob]
public class TaskAndValueTaskComparsion
{
[Benchmark]
public ValueTask<int> RunValueTaskWithNew()
{
return new ValueTask<int>(1);
}
[Benchmark]
public Task<int> RunTaskFromResult()
{
return Task.FromResult(1);
}
}
For the result, the Task<T> is way faster than ValueTask<T>. But why? I really expected the ValueTask<T> would cause less allocation when returning task objects.
Thanks for all the commenters. Let's summarize all these valuable info.
There is a TaskCache.cs in the .NET runtime that create cacheable Task for various primitive type's value such as true(bool), false(bool), -1 ~ 9(int). The Task.FromResult leverage these cached Task for it.
So, the benchmark result is incorrect because the Task.FromResult is always return cached version of Task object, and the new ValueTask<int>(1) always returns a new value.
For more information, please read Understanding the Whys, Whats, and Whens of ValueTask.
If you can read Chinese, I also wrote a post yesterday. See here.
Which of these is the best option when working with caching in C#?
I am interested at the compiler level which of these is the most elegant / performant solution.
E.g does the .net compiler use any tricks to know that when code will run synchronously and avoid creating/running unnecessary async await code?
Option 1, Use async/await and use Task.FromResult for cached values;
public async Task<T> GetValue<T>(string key)
{
if (_cache.containsKey(key))
{
// 99% of the time will hit this
return Task.FromResult(_cache.GetItem(key));
}
return await _api.GetValue(key);
}
Option 2, Avoid async/await and use something like GetAwaiter().GetResult() for the few times the API Endpoint will be hit.
public T GetValue<T>(string key)
{
if (_cache.containsKey(key))
{
// 99% of the time will hit this
return _cache.GetItem(key);
}
return _api.GetValue(key).GetAwaiter().GetResult();
}
Any insights would be very much appreciated.
The official approach is to cache the Task<T>, and not the T.
This also has the advantage that if someone requests the value, you can kick off the request to fetch the value and then cache the resulting, in-progress Task<T>. If someone else requests the cached value before the request has completed, they're also given the same in-progress Task<T>, and you don't end up making two requests.
For example:
public Task<T> GetValue<T>(string key)
{
// Prefer a TryGet pattern if you can, to halve the number of lookups
if (_cache.containsKey(key))
{
return _cache.GetItem(key);
}
var task = _api.GetValue(key);
_cache.Add(key, task);
return task;
}
Note that you need to think about failure in this case: if the request to the API fails, then you'll be caching a Task which contains an exception. This might be what you want, but it might not be.
If for some reason you can't do this, then the official advice is to use ValueTask<T> for high-performance scenarios. This type has some gotchas (such as you can't await it twice), so I recommend reading this. If you don't have high performance requirements, Task.FromResult is fine.
Your first won't work. The simplest, and the one to go for most of the time is:
public async Task<T> GetValueAsync<T>(string key)
{
if (_cache.ContainsKey(key))
{
return _cache.GetItem(key);
}
T result = await _api.GetValueAysnc(key);
_cache.Add(key, result);
return result;
}
Or better still if possible:
public async Task<T> GetValueAsync<T>(string key)
{
if (_cache.TryGet(key, out T result))
{
return result;
}
result = await _api.GetValueAysnc(key);
_cache.Add(key, result);
return result;
}
This works fine and will return an already-completed task when the value was in the cache, so awaiting it will continue immediately.
However if the value is in the cache much of the time and the method is called often enough for the extra apparatus around async to make a difference then you can avoid it entirely in such a case:
public Task<T> GetValueAsync<T>(string key)
{
if (_cache.TryGet(key, out Task<T> result))
{
return result;
}
return GetAndCacheValueAsync(string key);
}
private async Task<T> GetAndCacheValueAsync<T>(string key)
{
var task = _api.GetValueAysnc(key);
result = await task;
_cache.Add(key, task);
return result;
}
Here if the value is cached we avoid both the state-machine around async and also the creation of a new Task<T> since we have stored an actual Task. Each of these are only done in the first case.
What you are looking for probably is memoization.
A implementation might be something like this:
public static Func<T, TResult> Memoize<T, TResult>(this Func<T, TResult> f)
{
var cache = new ConcurrentDictionary<T, TResult>();
return a => cache.GetOrAdd(a, f);
}
Measure(() => slowSquare(2)); // 00:00:00.1009680
Measure(() => slowSquare(2)); // 00:00:00.1006473
Measure(() => slowSquare(2)); // 00:00:00.1006373
var memoizedSlow = slowSquare.Memoize();
Measure(() => memoizedSlow(2)); // 00:00:00.1070149
Measure(() => memoizedSlow(2)); // 00:00:00.0005227
Measure(() => memoizedSlow(2)); // 00:00:00.0004159
Source
First of all, this calls for linking the speed rant:
https://ericlippert.com/2012/12/17/performance-rant/
Microoptimisations like these are usually left to the JiT. My rule of thumb is that if you really need that difference, then you are propably dealing with realtime programming. And for Realtime Proramming a Garbage Collected runtime like .NET was propably the wrong environment to begin with. Something with direct memory management like unsafe code - even native C++ or Assembler - would have been better.
Secondly, a task might just be the wrong tool here. Maybe what you actually want is something like Lazy[T]? Or any of the 5 different Chache classes? (as with timer, there is about one for specific User Interface technology).
It is possible to use any tool for many purposes. But tasks are for Multitasking and there are better tools for caching and lazy initialisation. And Lazy[T] is even inherently Thread save.
I have an async method:
public async Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, string language, bool throwEx = true)
{
UserLoginExResult result = await UserService.LoginExAsync(UserGroup, language, TimezoneOffset, GetDeviceInfo(), GetLoginProperties(), exRequest);
ProcessLoginResult(result, false, throwEx);
return result;
}
And an overload:
public Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, bool throwEx = true)
{
return LoginExAsync(exRequest, Language.ID, throwEx);
}
I'm not sure if I should mark the overloaded one (the one with fewer parameters) as async and use await? I guess I should not but can you tell me what whould happen if I would do that? I'm quite lost in here and not really sure what Task it would wait for? Would it create an extra Task or await doesn't create a new Task?
No, there's little benefit in using an async method when it's just going to wrap and unwrap an existing one. It's fine to just have a "normal" method here, delegating to the "real" async method.
(They're not quite the same - for example, if the UserService.LoginExAsync method throws an exception rather than returning a failed task, the async/await version will just return a failed task, whereas the other version will also throw immediately.)
The async keyword only enables the await keyword. In your case, you can return the Task directly, so there's no need for the async keyword. async would only add overhead without adding any value.
For more information, see Stephen Toub's Zen of Async talk. He addresses this situation directly.
It would really only be worth doing if you were doing additional work in your overload, e.g.
public async Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, bool throwEx = true)
{
Task<UserLoginExResult> result = await LoginExAsync(exRequest, Language.ID, throwEx);
//Do some work here that depends on the result from the task completeion
return result;
}
But as you are not, it isn't!
The overload doesn't need to be marked as async as it doesn't internally await anything, so therefore there's nothing for the compiler to rewrite.
I want to write a class to simplify the asynchronous programing, like string s = mylib.BeginInvoek(test,"1"); here is my code:
public T BeginInvokeExWithReturnValue<T>(Func<T> actionFunction)
{
ExecWithReturnType<T> execWtihReturnValue = new ExecWithReturnType<T>(actionFunction);
IAsyncResult iar = execWtihReturnValue.BeginInvoke(new AsyncCallback(EndInvokeExWithReturnValue<T>), execWtihReturnValue);
// how to code here to return value
}
private void EndInvokeExWithReturnValue<T>(IAsyncResult iar)
{
ExecWithReturnType<T> execWtihReturnValue = (ExecWithReturnType<T>)iar.AsyncState;
execWtihReturnValue.EndInvoke(iar);
}
this BeginInvokeExWithReturnValue function has no input parameter, but returns a value,
But I don't know how to return a value from BeginInvokeExWithReturnValue function. Anyone who know this, Could you pls help me ? thx very much.
What you are trying to do right now is not async; if you want to return the T, just use:
return actionFunction();
It will be less overhead.
If you want async, and you are on 4.0, then the TPL may be a good option:
public Task<T> BeginInvokeExWithReturnValue<T>(Func<T> actionFunction)
{
var task = new Task<T>(actionFunction);
task.Start();
return task;
}
Now the caller can use:
var task = BeginInvokeExWithReturnValue(() => Whatever());
and then when desired, check for completion, block (Wait) for completion, register continuations, etc. Or just:
var result = task.Result; // implicit wait
Console.WriteLine(result);
This allows you to seamlessly write async code. Or in C# 5.0, seamlessly write continuations:
var result = await task; // continuation - this is **not** a wait
Console.WriteLine(result);
As David pointed out, the Invoke method is probably what you want, but if you're looking to write you're own variant, you just need to type cast the value to the generic (T, in your example) to satisfy your comment.
return (T) iar;
Following from the comments,
There are 3 models of Asyncronous development in .NET
APM - (BeginXXX EndXXX) Which you are using here, when the long running task completes it calls back into your code in the EndXXX method
EAP - Event based. In this model, when the long running task completes, an event is raised to inform your code.
TPL - New in .NET 4, this is the 'Task' based version. it looks most like Syncronous programming to client code, using a fluent interface. Its calls back to your code using continueWith.
Hope this helps
How would you implement something that works similarly to the Async CTP await keyword? Is there a simple implementation that works like await in all cases, or does await require different implementations for different scenarios?
The new await keyword has similar semantics to the existing yield return keyword in that they both cause the compiler to generate the continuation style state machine for you. So it is possible to hack something together using iterators that has some of the same behaviors as the Async CTP.
Here is what it would look like.
public class Form1 : Form
{
private void Button1_Click(object sender, EventArgs e)
{
AsyncHelper.Invoke<bool>(PerformOperation);
}
private IEnumerable<Task> PerformOperation(TaskCompletionSource<bool> tcs)
{
Button1.Enabled = false;
for (int i = 0; i < 10; i++)
{
textBox1.Text = "Before await " + Thread.CurrentThread.ManagedThreadId.ToString();
yield return SomeOperationAsync(); // Await
textBox1.Text = "After await " + Thread.CurrentThread.ManagedThreadId.ToString();
}
Button2.Enabled = true;
tcs.SetResult(true); // Return true
}
private Task SomeOperationAsync()
{
// Simulate an asynchronous operation.
return Task.Factory.StartNew(() => Thread.Sleep(1000));
}
}
Since yield return generates an IEnumerable our coroutine must return an IEnumerable. All of the magic happens inside the AsyncHelper.Invoke method. This is what gets our coroutine (masquerading as a hacked iterator) going. It takes special care to make sure the iterator is always executed on the current synchronization context if one exists which is important when trying to simulate how await works on a UI thread. It does this by executing the first MoveNext synchronously and then using SynchronizationContext.Send to do the rest from a worker thread which is also used to asynchronously wait on the individual steps.
public static class AsyncHelper
{
public static Task<T> Invoke<T>(Func<TaskCompletionSource<T>, IEnumerable<Task>> method)
{
var context = SynchronizationContext.Current;
var tcs = new TaskCompletionSource<T>();
var steps = method(tcs);
var enumerator = steps.GetEnumerator();
bool more = enumerator.MoveNext();
Task.Factory.StartNew(
() =>
{
while (more)
{
enumerator.Current.Wait();
if (context != null)
{
context.Send(
state =>
{
more = enumerator.MoveNext();
}
, null);
}
else
{
enumerator.MoveNext();
}
}
}).ContinueWith(
(task) =>
{
if (!tcs.Task.IsCompleted)
{
tcs.SetResult(default(T));
}
});
return tcs.Task;
}
}
The whole bit about the TaskCompletionSource was my attempt at replicating the way await can "return" a value. The problem is that the coroutine has to actually return an IEnumerable since it is nothing more than a hacked iterator. So I needed to come up with an alternate mechanism to capture a return value.
There are some glaring limitations with this, but I hope this gives you the general idea. It also demonstrates how the CLR could have one generalized mechanism for implementing coroutines for which await and yield return would use ubiquitously, but in different ways to provide their respective semantics.
await always involves the same kind of transformation - but it's a pretty painful one. The library side of await isn't too complicated, but the tricky bit is that the compiler builds a state machine for you, allowing the continuation to jump back to the right place.
It's possible that my some hacky use of iterator blocks (yield return) you could fake something similar... but it would be pretty ugly.
I gave a DevExpress webinar on what the compiler is doing behind the scenes a few weeks ago - that shows decompiled code from a couple of examples, as well as explaining how the compiler builds a task to return, and what the "awaiter" has to do. It may be useful to you.
There are few implementations and examples of coroutines made out of iterators (yield).
One of the examples is Caliburn.Micro framework, that uses this patter for asynchronous GUI operations. But it can easily be generalised for general async code.
The MindTouch DReAM framework implements Coroutines on top of the Iterator pattern which is functionally very similar to Async/Await:
async Task Foo() {
await SomeAsyncCall();
}
vs.
IYield Result Foo() {
yield return SomeAsyncCall();
}
Result is DReAM's version of Task. The framework dlls work with .NET 2.0+, but to build it you need 3.5, since we're using a lot of 3.5 syntax these days.
Bill Wagner from Microsoft wrote an article in MSDN Magazine about how you can use the Task Parallel Library in Visual Studio 2010 to implement async like behavior without adding a dependency on the async ctp.
It uses Task and Task<T> extensively which also has the added benefit that once C# 5 is out, your code will be well prepared to start using async and await.
From my reading, the major differences between yield return and await is that await can provide explicitly return a new value into the continuation.
SomeValue someValue = await GetMeSomeValue();
whereas with yield return, you'd have to accomplish the same thing by reference.
var asyncOperationHandle = GetMeSomeValueRequest();
yield return asyncOperationHandle;
var someValue = (SomeValue)asyncOperationHandle.Result;