To use this method :
public static Task Run(Action action)
I just write :
void MyMethod(){ //do something }
Task t = Task.Run(new Action(MyMethod));
However I do not understand how to use the following overload
public static Task Run(Func<Task> f)
The msdn mentions that the returned task is "a proxy for the task
returned by f" which is even more confusing to me. What is meant by proxy and how would I call this method?
Func<Task> is simply a function that returns a task. That task is then executed.
So Task Run( Func<Task> f ) returns a Task, whose job is to run another Task (the one created by f). That's what's meant by a "proxy".
However, read the Note on MSDN (emphasis added):
The Run<TResult>(Func<Task<TResult>>) method is used by language compilers to support the async and await keywords. It is not intended to be called directly from user code.
Func<T> is a generic delegate - here's its full signature:
public delegate TResult Func<out TResult>()
As you can see, it represents a function that takes no parameters, and returns an instance of type TResult. In the case of Func<Task>, TResult is Task.
What this means, is that you can do this:
public Task MyAsyncMethod() { ... }
Task.Run(MyAsyncMethod);
This converts your method MyAsyncMethod into a delegate of type Func<Task> and passes it to Task.Run. It's syntactic sugar for Task.Run( new Func<Task>(MyAsyncMethod) );
The msdn mentions that the returned task is "a proxy for the task returned by f" which is even more confusing to me (what is meant by proxy ?)
What this means is that Task.Run will simply wrap the task returned by MyAsyncMethod is another Task.
That signature allows you to provide a method that returns a Task, when you run Task.Run. That is because the last generic argument of a Func<T> is the return value given back by the delegate you provide. Meaning:
public Func<bool> IsValid = this.ValidateUser;
public bool ValidateUser() { return someUser.IsAuthenticated; }
or even just
public Func<bool> IsValidUser = this.User.IsAuthenticated;
Then you can use the delegate as you would any other method, and the delegate will return a bool.
public void Foo()
{
if (!IsValidUser()) throw new InvalidOperationException("Invalid user");
}
You can use parameters that are passed in to the delegate, by providing additional generic types other than the return value.
Func<int, bool> IsUserAgeValid = (age) => return age > 18;
// Invoke the age check
bool result = this.IsUserAgeValid(17);
The thing to remember is that the last generic is always the return type in a Func. If only one generic is provided, then there is no parameters, only a return type.
A Func<Task> allows you to use an awaitable method in your Task.Run call.
This also means that you can await from within the anonymous delegate you provide.
public Task Foo()
{
/* .. do stuff */
}
public void Bar()
{
Task.Run(async () =>
{
await Foo();
/* do additional work */
});
}
and if you don't need to await the call to Foo(), you can just give Task.Run the Foo method.
Task.Run(Foo);
If you find yourself wanting to await the awaitable method given to Task.Run as shown above, it is probably better that you use ContinueWith.
public void Bar()
{
Task.Run(Foo).ContinueWith(foosTaskResult =>
{
/* Do stuff */
});
}
The MSDN documentation saying the the Task returned is a proxy for the Task of f, basically means that
Task returnedTask = Task.Run(Foo);
will set returnedTask to be the Task that was returned by the call to the awaitable Foo() method.
a Func<T> refers to a method which returns T, which in this case is a Task. Thus, to make MyMethod compatible with this particular overload, you would write
Task MyMethod() {...}
Which also means you could make MyMethod and async method, thus
async Task MyMethod() {...}
When referring to a "proxy" this means that the Task returned by Task.Run isn't actually the task returned by MyMethod, but instead wraps it.
Related
By the time the code calls Task.Result, it has already been awaited, so does the asynchronous pattern here still hold?
class Program
{
static async Task Main(string[] args)
{
var addNumbersTask = AddNumbers(10, 20);
var result = AwaitForResult(addNumbersTask).Result;
Console.WriteLine(result);
}
static async Task<int> AddNumbers(int a, int b)
{
await Task.Delay(250);
return a + b;
}
static async Task<int> AwaitForResult(Task<int> task)
{
await task;
return task.Result;
}
}
Background if you're interested: Trying to emit IL code for a proxy class that needs to handle async calls, but I don't want to generate the async state machine in the IL. So I figured I could delegate the actual "await" part to a helper outside of the IL. Also, I know there are proxy types out there but the hopeless engineer in me wants to write it myself.
Edit: Updated example.
interface IService
{
Task<int> AddAsync(int a, int b);
}
class Service : IService
{
public async Task<int> AddAsync(int a, int b)
{
await Task.Delay(250); // Some web service call...
return a + b;
}
}
// This class 100% generated via reflection emit
class Proxy : IService
{
private readonly IService _actual;
public Proxy(IService actual) => _actual = actual;
public Task<int> AddAsync(int a, int b)
{
return Awaiter.Await(_actual.AddAsync(a, b));
}
}
static class Awaiter
{
public static async Task<int> Await(Task<int> task)
{
return await task;
}
}
class Program
{
static async Task Main(string[] args)
{
var proxy = new Proxy(new Service());
var result = await proxy.AddAsync(5, 5);
Console.WriteLine($"Result is {result}", result);
}
}
does the asynchronous pattern here still hold?
No. There's nothing magical about using await on a task. Instead, consider whether the task is completed. Calling task.Result will block the calling thread until task completes. Doing await task will asynchronously wait until task completes.
So in this code, Result will not block:
static async Task<int> AwaitForResult(Task<int> task)
{
// Task may not yet be complete here.
await task;
// At this point, task is complete.
// Since task is complete, Result does not block.
return task.Result;
}
But that is totally different than this code:
var result = AwaitForResult(addNumbersTask).Result;
// Equivalent to:
var task = AwaitForResult(addNumbersTask);
var result = task.Result;
The task returned from AwaitForResult may not be complete here, since it was never awaited. And if it's not complete, then Result will block.
Trying to emit IL code for a proxy class that needs to handle async calls, but I don't want to generate the async state machine in the IL. So I figured I could delegate the actual "await" part to a helper outside of the IL.
Have you tried Roslyn APIs? I find them much more convenient than IL emit.
If your proxy is just a pass-through, then you can just return the inner task directly:
// This class 100% generated via reflection emit
class Proxy : IService
{
private readonly IService _actual;
public Proxy(IService actual) => _actual = actual;
public Task<int> AddAsync(int a, int b) => _actual.AddAsync(a, b);
}
But if you want to add much real logic, then I'd recommend using Roslyn to generate the async state machine for you.
If you’re trying to avoid blocking, then no.
In your console app example it makes little difference, but if you did that somewhere where you don’t want blocking - e.g. a UI event handler - .Result will still block.
By the time you have a value in addNumbersTask, that task is started. You then immediately pass the task to AwaitForResult, which immediately begins to await it, at which point an incomplete task that returns an int is returned back to main(), and you then call .Result on it. You are now blocking that thread for most of the 250ms until that task returns its int result to .Result in main().
The way you have expressed it in the question, “awaited” does not equal “completed”.
The method Awaiter.Await is basically pointless. Outside of adding some overhead, the returned task will be functionally identical to the one passed in.
The only actual difference in code between simply returning the result of _actual.AddAsync(a, b) and awaiting it is that, if AddAsync throws an exception, if the method is async it will return a faulted task instead of throwing. So if that either can't happen, or if Proxy.AddAsync can safely throw itself in that situation, then simply return the value, no need to do anything. If you need to ensure that Proxy.AddAsync never throws an exception, and instead returns a faulted task if Proxy.AddAsync throws an excpetion, then you simply need to wrap the method in a try/catch and return a faulted exception in the catch block. You don't need to replicate any of the rest of the logic of the async state machine.
So assuming you want the same exception semantics as the behavior of the service's method, which I suspect you do, you can treat these methods exactly the same as you would a synchronous method, that is to say invoke the method with the appropriate parameters and return the result.
My understanding is that async void, should be avoided and that async () => is just async void in disguise when used with Action.
Hence, using the Rx.NET Finally operator asynchronously with async () => should be avoided since Finally accepts Action as parameter:
IObservable<T>.Finally(async () =>
{
await SomeCleanUpCodeAsync();
};
However, if this is bad practise, what is then best practice to use in the case where I for instance need to asynchronously close a network connection on OnCompleted or if my observable end with OnError?
My understanding is that async void, should be avoided and that async
() => is just async void in disguise.
This is partially wrong. async () => can either match Func<Task> (good) or Action (bad). The main reason for good/bad is that an exception that occurs in a async void call crashes the process, whereas a async Task exception is catchable.
So we just need to write an AsyncFinally operator that takes in a Func<Task> instead of an Action like Observable.Finally:
public static class X
{
public static IObservable<T> AsyncFinally<T>(this IObservable<T> source, Func<Task> action)
{
return source
.Materialize()
.SelectMany(async n =>
{
switch (n.Kind)
{
case NotificationKind.OnCompleted:
case NotificationKind.OnError:
await action();
return n;
case NotificationKind.OnNext:
return n;
default:
throw new NotImplementedException();
}
})
.Dematerialize()
;
}
}
And here's a demonstration of usage:
try
{
Observable.Interval(TimeSpan.FromMilliseconds(100))
.Take(10)
.AsyncFinally(async () =>
{
await Task.Delay(1000);
throw new NotImplementedException();
})
.Subscribe(i => Console.WriteLine(i));
}
catch(Exception e)
{
Console.WriteLine("Exception caught, no problem");
}
If you swap out AsyncFinally for Finally, you'll crash the process.
It is in Rx as it is elsewhere; avoid async void like the plague. In addition to the problems listed in the article, using asynchronous code in the synchronous operators "breaks" Rx.
I'd consider using OnErrorResumeNext() for cleaning up resources asynchronously. OnErrorResumeNext() let's you specify an observable which will run after the first, regardless the reason it ended:
var myObservable = ...
myObservable
.Subscribe( /* Business as usual */ );
Observable.OnErrorResumeNext(
myObservable.Select(_ => Unit.Default),
Observable.FromAsync(() => SomeCleanUpCodeAsync()))
.Subscribe();
myObservable would preferably be a ConnectableObservable (e.g. Publish()) to prevent multiple subscriptions.
The method signature for Finally is
public static IObservable<TSource> Finally<TSource>(
this IObservable<TSource> source,
Action finallyAction
)
which expects an action, not a Task.
As an addendum, if you want to run something asynchronously, instead of async void, use Task.Factory methods inside the method so the intention is explicit.
Quoting from the Intro to Rx:
The Finally extension method accepts an Action as a parameter. This Action will be invoked if the sequence terminates normally or erroneously, or if the subscription is disposed of.
(emphasis added)
This behavior cannot be replicated by a Finally operator that accepts a Func<Task> parameter, because of how the IObservable<T> interface is defined. Unsubscribing from an observable sequence is achieved by calling the Dispose method of the IDisposable subscription. This method is synchronous. And the whole Rx library is built on top of this interface. So even if you create an extension method DisposeAsync for IDisposables, the built-in Rx operators (for example Select, SelectMany, Where, Take etc) will be unaware of its existence, and will not invoke it when they unsubscribe from their source sequence. A subscription chain of operators will be automatically unlinked by calling the synchronous Dispose method of the previous link as always.
Btw there has been an attempt to implement an asynchronous version of Rx (AsyncRx), that is built on top of the completely new interfaces that are shown below. This library has not been released yet.
public interface IAsyncObserver<in T>
{
ValueTask OnNextAsync(T value);
ValueTask OnErrorAsync(Exception error);
ValueTask OnCompletedAsync();
}
public interface IAsyncObservable<out T>
{
ValueTask<IAsyncDisposable> SubscribeAsync(IAsyncObserver<T> observer);
}
public interface IAsyncDisposable
{
public ValueTask DisposeAsync();
}
I have the interface:
public interface IService
{
Task<double> GetData(int id);
}
And I need to use this interface in my class:
//_svc is a Type of IService
public async void Doit()
{
Task<double> task = await _svc.GetData(id);
}
And when I do it, it says that it can't convert type double into Task<double>
Why is this double instead of the task? The interface clearly specifies that this is a task and here I need to get the task, not the value.
If you need the task to handle it yourself, then remove the await that handles it for you.
It is not an answer, but i hope it will help you to understand Tasks a little bit more. For example you have interface with method:
System.Threading.Tasks.Task<string> FindNameAsync(string computerName);
When you call a method from interface, it will be something like this:
var result = await _scv.FindNameAsync(name); //The program will not go to next line, until it becomes result
When it will get result it will go further. And result you can pass to next methods
EDIT
If you want to get statuses you can make little modifications:
System.Threading.Tasks.Task<bool> FindNameAsync(string computerName);
Then you can return true in case of success, in other case - false.
With a little modification you can pass object to method as parameter and save values that you need in it. Or you can return dictionary or turple, and not bool. Little example:
Your method can be like here:
System.Threading.Tasks.Task<bool> FindNameAsync(SomeClass obj);
And you can handle it so:
SomeClass test = new SomeClass();
if(await _scv.FindNameAsync(test))
{
//code for success result
}else
{
//if error happened handle here
}
The interface clearly specifies that this is a task and here I need to get the task, not the value.
When an interface declares a method that returns a Task or Task<T> the name of the method should - by convention - also end with "Async": https://msdn.microsoft.com/en-us/library/hh191443
Such a method is expected to be implemented as an async method that returns an object of type T if the return type is declared as Task<T> or nothing at all if the return type is just Task:
public interface IService
{
Task<double> GetDataAsync(int id);
}
public class Service : IService
{
public async Task<double> GetDataAsync(int id)
{
await Task.Delay(1000);
return 1.0;
}
}
You would await such a method:
public class Consumer
{
public async void Doit()
{
IService service = new Service();
double d = await service.GetDataAsync(1);
}
}
Now whether the method actually is implemented as an async method is an implementation detail in the concrete implementation of the interface but it doesn't really matter as far as the consumer of the interface is concerned as you can still always await a method that returns Task or Task (provided that the caller method is marked with the async keyword of course).
You would for example be able to await the following non-async implementation of the method the same way:
public class Service : IService
{
public Task<double> GetDataAsync(int id)
{
return Task.FromResult(1.0);
}
}
So methods that have a return type of Task or Task<T> are meant to be asynchronous and awaited.
You could still store an instance of the method's actual return type in a variable "as usual" though:
public void Doit()
{
IService service = new Service();
Task<double> task = service.GetDataAsync(1);
}
This would however simply call the asynchronous without waiting for its return value which makes it pretty useless to even call the method in the first place. When calling a - by contract and convention asynchronous - method that returns a Task<double> you are interested in getting the double value back asynchronously. You don't really care about the Task object itself if you understand what I mean.
I have a virtual method that sometimes contain await calls and sometimes doesn't. The IDE does give me warning, what is the proper way of handling this ?
In my base class:
protected virtual async Task GoNext ()
From the base class it get called via await.
Then in my sub-classes i override this method but there are times that it does include a await and times that it doesn't.
The async keyword is not actually part of the inherited method signature, but more of a signal to the compiler that it needs to compile and rewrite the method according to the pattern for async methods.
As such, you can leave out the async keyword on inherited methods if the inherited method does not use the await keyword.
Note that you will still have to return a Task or Task<T>, that part is part of the inherited method signature.
So this will give you a warning:
class Base
{
public virtual async Task<int> Method()
{
await Task.Delay(10);
return 42;
}
}
class Derived : Base
{
// next line produces warning
public override async Task<int> Method()
{
return 42;
}
}
The warning is this:
Warning: CS1998 This async method lacks 'await' operators and will run synchronously. Consider using the await operator to await non-blocking API calls, or await Task.Run(...) to do CPU-bound work on a background thread.
This, however, will not produce a warning:
class Derived : Base
{
public override Task<int> Method()
{
return Task.FromResult(42);
}
}
Note that I changed the return statement in that last method because part of the "magic" that the async keyword brings is to automatically wrap the return value inside a Task<T>. If you have other ways of obtaining a Task<T>, obviously you do not need to wrap the result like I did above.
In contrast to Task.Wait() or Task.Result, await’ing a Task in C# 5 prevents the thread which executes the wait from lying fallow. Instead, the method using the await keyword needs to be async so that the call of await just makes the method to return a new task which represents the execution of the async method.
But when the await’ed Task completes before the async method has received CPU time again, the await recognizes the Task as finished and thus the async method will return the Task object only at a later time. In some cases this would be later than acceptable because it probably is a common mistake that a developer assumes the await’ing always defers the subsequent statements in his async method.
The mistaken async method’s structure could look like the following:
async Task doSthAsync()
{
var a = await getSthAsync();
// perform a long operation
}
Then sometimes doSthAsync() will return the Task only after a long time.
I know it should rather be written like this:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Run(() =>
{
// perform a long operation
};
}
... or that:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Yield();
// perform a long operation
}
But I do not find the last two patterns pretty and want to prevent the mistake to occur. I am developing a framework which provides getSthAsync and the first structure shall be common. So getSthAsync should return an Awaitable which always yields like the YieldAwaitable returned by Task.Yield() does.
Unfortunately most features provided by the Task Parallel Library like Task.WhenAll(IEnumerable<Task> tasks) only operate on Tasks so the result of getSthAsync should be a Task.
So is it possible to return a Task which always yields?
First of all, the consumer of an async method shouldn't assume it will "yield" as that's nothing to do with it being async. If the consumer needs to make sure there's an offload to another thread they should use Task.Run to enforce that.
Second of all, I don't see how using Task.Run, or Task.Yield is problematic as it's used inside an async method which returns a Task and not a YieldAwaitable.
If you want to create a Task that behaves like YieldAwaitable you can just use Task.Yield inside an async method:
async Task Yield()
{
await Task.Yield();
}
Edit:
As was mentioned in the comments, this has a race condition where it may not always yield. This race condition is inherent with how Task and TaskAwaiter are implemented. To avoid that you can create your own Task and TaskAwaiter:
public class YieldTask : Task
{
public YieldTask() : base(() => {})
{
Start(TaskScheduler.Default);
}
public new TaskAwaiterWrapper GetAwaiter() => new TaskAwaiterWrapper(base.GetAwaiter());
}
public struct TaskAwaiterWrapper : INotifyCompletion
{
private TaskAwaiter _taskAwaiter;
public TaskAwaiterWrapper(TaskAwaiter taskAwaiter)
{
_taskAwaiter = taskAwaiter;
}
public bool IsCompleted => false;
public void OnCompleted(Action continuation) => _taskAwaiter.OnCompleted(continuation);
public void GetResult() => _taskAwaiter.GetResult();
}
This will create a task that always yields because IsCompleted always returns false. It can be used like this:
public static readonly YieldTask YieldTask = new YieldTask();
private static async Task MainAsync()
{
await YieldTask;
// something
}
Note: I highly discourage anyone from actually doing this kind of thing.
Here is a polished version of i3arnon's YieldTask:
public class YieldTask : Task
{
public YieldTask() : base(() => { },
TaskCreationOptions.RunContinuationsAsynchronously)
=> RunSynchronously();
public new YieldAwaitable.YieldAwaiter GetAwaiter()
=> default;
public new YieldAwaitable ConfigureAwait(bool continueOnCapturedContext)
{
if (!continueOnCapturedContext) throw new NotSupportedException();
return default;
}
}
The YieldTask is immediately completed upon creation, but its awaiter says otherwise. The GetAwaiter().IsCompleted always returns false. This mischief makes the await operator to trigger the desirable asynchronous switch, every time it awaits this task. Actually creating multiple YieldTask instances is redundant. A singleton would work just as well.
There is a problem with this approach though. The underlying methods of the Task class are not virtual, and hiding them with the new modifier means that polymorphism doesn't work. If you store a YieldTask instance to a Task variable, you'll get the default task behavior. This is a considerable drawback for my use case, but I can't see any solution around it.