Getting double instead of the task in C# Task, why? - c#

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.

Related

How do you handle a 3rd party interface returning Task if you don't have any async code? [duplicate]

This question already has answers here:
How to implement interface method that returns Task<T>?
(4 answers)
Closed 6 years ago.
I am working with a third-party dll which exposes methods which return Task and Task<T>. I don't have any control over this assembly or the interface, and I assume the author assumed everything would need to be async since the naming of the methods are *Async() as shown below.
Given that, how do I properly implement the interface if I don't actually have any asynchronous code running?
public interface IFoo
{
Task DoWorkAsync();
Task<int> GetValueAsync();
}
My attempt was the following:
public class FooBar : IFoo
{
public async Task DoWorkAsync()
{
// Do Some Work
await Task.Yield();
}
public async Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
Additionally:
Was the author correct in exposing only methods that returned Task/Task<T>?
Was the author correct in suffixing method names with *Async()? Code analysis doesn't complain if I write an async method without appending Async to the name.
If you don't have async work to do don't include the async keyword. Your GetValueAsnyc function was almost correct, you just needed to drop the async. For your DoWorkAsync you should just not mark the method async and return a completed task.
public class FooBar : IFoo
{
public Task DoWorkAsync()
{
// Do Some Work
//If you can use .NET 4.6
return Task.CompletedTask;
//For older versions, the thing you pass in does not matter, I like to use bool.
return Task.FromResult(false);
}
public Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
However, if your code is slow and you end up blocking the UI for a long period of time I would consider looking in to if you can re-write your code as actually being async or perhaps wrapping the code in to a background thread, but I would only do a background thread if it was a last resort.

Async/Await without await call

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.

How can I use the Task.Run(Func<Task> f) method signature?

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.

Implication of calling result on awaited task

Given we have some kind of rudimentary async CQRS setup like the below:
public interface IRequest<TReturn> { }
public interface IRequestHandler<TRequest, TReturn> where TRequest : IRequest<TReturn>
{
Task<TReturn> RequestAsync<TRequest>(TRequest request);
}
public class GetThings : IRequest<string[]> { }
public class GetThingsHandler : IRequestHandler<GetThings, string[]>
{
public async Task<string[]> RequestAsync<TRequest>(TRequest request)
{
await Task.Run(() => Thread.Sleep(200));
return new[] {"Tim", "Tina", "Tyrion"};
}
}
And we have some kind of dependency injection container:
public class Container
{
public object Resolve(Type serviceType)
{
var possibleTypes = new Dictionary<Type, object>();
possibleTypes.Add(typeof(GetThings), new GetThingsHandler());
return possibleTypes[serviceType];
}
}
For our 'RequestBus' implementation, all generic type parameter information is lost, due to being on the other end of a REST style service:
public async Task<object> GetRequest(object o)
{
Type t = o.GetType();
object handler = container.Resolve(t);
var methodInfo = handler.GetType().GetMethod("RequestAsync");
methodInfo = methodInfo.MakeGenericMethod(typeof (object));
Task methodInvocationTask = (Task)methodInfo.Invoke(handler, new[] {o});
await methodInvocationTask;
// Or: return ((dynamic) methodInvocationTask).Result;
return methodInvocationTask.GetType().GetProperty("Result").GetValue(methodInvocationTask);
}
The only thing that is known is that all tasks may return an object and that we can deduce the type of the request and request return type (it is treated as known here for simplicity).
The question is:
Is calling await on the (void) Task before asking for Task.Result actually executing in an async way? Assuming the handler does actual async work is this method going to be properly async?
(Note: these are simplified implementations for the sake of asking a question)
If you await the task then the rest of the method is executed as a continuation of that Task and control is returned to the caller of the current method, so yes, it'll be asynchronous.
That is the point of await after all; to behave asynchronously.
Calling Result on an already completed Task isn't a problem. It will block the current thread until the Task has completed, but as you know it's already completed, that's not a problem.

Generic constraint based on non-implementation of interface

I have an application with a factory service to allow construction of instances while resolving the necessary dependency injection. For instance, I use this to construct dialog view models. I have a service interface that looks like this:
public interface IAsyncFactory
{
Task<T> Build<T>() where T: class, IAsyncInitialize;
}
Ideally, what I'd like to have is something like this (pseudo-syntax, as this isn't directly achievable)
public interface IFactory
{
Task<T> Build<T>() where T: class, IAsyncInitialize;
T Build<T>() where T: class, !IAsyncInitialize;
}
The idea here is that if a class supports IAsyncInitialize, I'd like the compiler to resolve to the method that returns Task<T> so that it's obvious from the consuming code that it needs to wait for initialization. If the class does not support IAsyncInitialize, I'd like to return the class directly. The C# syntax doesn't allow this, but is there a different way to achieve what I'm after? The main goal here is to help remind the consumer of the class of the correct way to instantiate it, so that for classes with an asynchronous initialization component, I don't try to use it before it has been initialized.
The closest I can think of is to create separate Build and BuildAsync methods, with a runtime error if you call Build for an IAsyncInitialize type, but this doesn't have the benefit of catching errors at compile time.
In general Microsoft suggests to add async suffix when naming asynchronous methods. Thus, your assumption of creating two methods named as Build and BuildAsync makes sense.
I think there is no way to enforce something like "all types that do not implement IAsyncInitialize shall use Build method instead of BuildAsync" unless you force the developers to mark synchronous methods with another interface like ISynchronousInitialize.
You may try the following;
instead of having to separate methods, just implement one BuildAsync method which has the following signature:
Task<T> BuildAsync<T>() where T: class
In the BuildAsync method check whether T implements IAsyncInitialize. If this is the case, just call related initialization code after creating the object of type T. Otherwise, just create a TaskCompletionSource object and run the synchronous initialization code as if it is asynchronous.
The following approach might not be the best, but I find it very convenient. When both asynchronous and synchronous initializers are available (or possibly can be available), I wrap the synchronous one as asynchronous with Task.FromResult, and only expose the asynchronous method to the client:
public interface IAsyncInitialize
{
Task InitAsync();
int Data { get; }
}
// sync version
class SyncClass : IAsyncInitialize
{
readonly int _data = 1;
public Task InitAsync()
{
return Task.FromResult(true);
}
public int Data { get { return _data; } }
}
// async version
class AsyncClass: IAsyncInitialize
{
int? _data;
public async Task InitAsync()
{
await Task.Delay(1000);
_data = 1;
}
public int Data
{
get
{
if (!_data.HasValue)
throw new ApplicationException("Data uninitalized.");
return _data.Value;
}
}
}
This leaves only the asynchronous version of the factory:
public interface IAsyncFactory
{
// Build can create either SyncClass or AsyncClass
Task<T> Build<T>() where T: class, IAsyncInitialize;
}
Furthermore, I prefer to avoid dedicated initializer methods like InitAsync, and rather expose asynchronous properties directly as tasks:
public interface IAsyncData
{
Task<int> AsyncData { get; }
}
// sync version
class SyncClass : IAsyncData
{
readonly Task<int> _data = Task.FromResult(1);
public Task<int> AsyncData
{
get { return _data; }
}
}
// async versions
class AsyncClass : IAsyncData
{
readonly Task<int> _data = GetDataAsync();
public Task<int> AsyncData
{
get { return _data; }
}
private static async Task<int> GetDataAsync()
{
await Task.Delay(1000);
return 1;
}
}
In either case, it always imposes asynchrony on the client code, i.e.:
var sum = await provider1.AsyncData + await provider2.AsyncData;
However, I don't think it's an issue as the overhead of Task.FromResult and await Task.FromResult for the synchronous version is quite low. I'm going to post some benchmarks.
The approach using asynchronous properties can be further improved with Lazy<T>, e.g. like this:
public class AsyncData<T>
{
readonly Lazy<Task<T>> _data;
// expose async initializer
public AsyncData(Func<Task<T>> asyncInit, bool makeThreadSafe = true)
{
_data = new Lazy<Task<T>>(asyncInit, makeThreadSafe);
}
// expose sync initializer as async
public AsyncData(Func<T> syncInit, bool makeThreadSafe = true)
{
_data = new Lazy<Task<T>>(() =>
Task.FromResult(syncInit()), makeThreadSafe);
}
public Task<T> AsyncValue
{
get { return _data.Value; }
}
}

Categories