use task<string> method in overriden - c#

I would like to know whats the ideal way to call a method that returns a Task inside an override method?
For example:
public Task<string> GetName()
{
return Task.Run(() => {
return "Foo";
});
}
In one of my methods I would just simple do this:
public async Task<string> DoSomething()
{
var res = await GetName();
return res + " rocks";
}
But now I am facing a situation where there is a method delcared like this:
public virtual string DoSomething()
{
//does something...
}
In my inheritance I need to override this method and do some stuff and call a Task method, so my first thought was to do this:
public override async Task<string> DoSomething()
{
//does something...
base.DoSomething();
var res = await GetName();
return res + " rocks";
}
This clearly isnt possible since I changed the return value from a overriden method from string to Task string...
How should I solve my problem?
(Note: I cannot modify the base class, since its not mine. Its an external libary.)

You could do this:
public override string DoSomething()
{
//does something...
base.DoSomething();
return GetName().Result;
}
Warning: this can cause a deadlock
See Don't block on async code

Related

Make ProcessCmdKey async await - C# [duplicate]

I am overriding a method in a base class library. However, inside my overridden implementation I am using the new HttpClient which is all based on async methods. I therefore have to mark my method as async, which means that I need to change the return parameter of the method from string to Task. The compiler however gives an error: "The return type must be 'string' to match overridden member ...."
public class BaseClass
{
public virtual string GetName()
{
...
}
}
public class MyClass : BaseClass
{
public override async Task<string> GetName()
{
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetAsync("");
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
return await responseContent.ReadAsStringAsync();
}
return null;
}
}
Of course the obvious solution would be to change the return type of GetName() in BaseClass to Task<string>, but I have no control over BaseClass as it is an external library;
My current solution is to use the HttpClient classes in a synchronous fashion, i.e. change MyClass as follows:
public class MyClass : BaseClass
{
public override string GetName()
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync("");
if (response.Result.IsSuccessStatusCode)
{
var responseContent = response.Result.Content;
return responseContent.ReadAsStringAsync()
.Result;
}
return null;
}
}
Is there any other way to do this?
Unfortunately there isn't a good solution here. There is no way to override a non-async method with an async one. I think your best bet is to have an async non-override method and call into that from the non-async one:
public class MyClass : BaseClass
{
public override string GetName()
{
return GetNameAsync().Value;
}
public async Task<string> GetNameAsync()
{
...
}
}
Note that this can cause problems though. If the original code didn't expect for any async code to be executing introducing this pattern could break expectations. I would avoid it if possible.
Luckily the ReadAsStringAsync().Result is not causing a deadlock since it is likely to have ConfigureAwait(false) within.
To prevent a deadlock, you could use one of the following methods:
public static T GetResult<T>(Func<Task<T>> func)
{
var httpContext = HttpContext.Context;
var proxyTask = Task.Run(() =>
{
HttpContext.Context = httpContext;
return func();
});
return proxyTask.Result;
}
// or
public static T GetResult<T>(Func<Task<T>> func)
{
var syncContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
var task = func();
SynchronizationContext.SetSynchronizationContext(syncContext);
return task.Result;
}
This way you would call
public override string GetName()
{
...
return GetResult(() => responseContent.ReadAsStringAsync());
...
}
The former has a performance overhead by spawning a new thread, while the latter suffers from breaking SynchronizationContext flow, which makes any context bound to it unavailable in the task being called, e.g. HttpContext.Current.
I've also had this problem, and the solution was using an interface, in which 'async' isn't part of the method's signature.
public abstract class Base : IInvokable {
/* Other properties ... */
public virtual async Task Invoke() {
/*...*/
}
}
public interface IInvokable {
Task Invoke();
}
public class Derived
{
public override async Task Invoke() {
// Your code here
}
}

How to use action delegate to avoid if else

I have the following code:
public class NotificationService {
private readonly Dictionary<NotificationMessageType, Action<IList<RecipientDetail>, NotificationMessageType>> _actionMap;
public NotificationService() [
_actionMap = new Dictionary<NotificationMessageType, Action<IList<RecipientDetail>, NotificationMessageType>> ();
_actionMap.Add(NotificationMessageType.SessionBookedReminder, new Action<IList<RecipientDetail>, NotificationMessageType>(GenerateNotificationsAsync)); //getting errror here because of async await
}
public async Task GenerateNotificationsAsync(IList<RecipientDetail> usersToNotify, NotificationMessageType messageType)
{
Would like to avoid if else here:
if(messageType == NotificationMessageType.SessionBookedReminder)
{
await Task.WhenAll(usersToNotify.Select(u => GenerateBookingNotificationAsync(u, messageType)).ToArray());
}
else
{
await Task.WhenAll(usersToNotify.Select(u => SendNotificationAsync(u, messageType)).ToArray());
}
}
public async Task GenerateNotificationsAsync(IList<RecipientDetail> usersToNotify, NotificationMessageType messageType)
{
}
public async Task GenerateBookingNotificationAsync(RecipientDetail userToNotify, NotificationMessageType messageType)
{
}
}
How can I use action delegate to avoid if else. I've tried with following, but getting error due to async await.
Can anyone help how to do the right way?
Thanks
Your dictionary must match the method declaration, your methods returns a task, so your
Action<IList<RecipientDetail>, NotificationMessageType>
Must be changed to something like
Func<IList<RecipientDetail>, NotificationMessageType,Task>
your method must return a task in order to use it in a async/await manner

Get method name and parameters when it's invoked through a task queue

I have a simple task queue that allows one task to execute at a time:
public class TaskQueue
{
public SemaphoreSlim semaphore;
public TaskQueue()
{
semaphore = new SemaphoreSlim(1);
}
public async Task<T> Enqueue<T>(Func<Task<T>> taskGenerator)
{
await semaphore.WaitAsync();
try
{
return await taskGenerator();
}
finally
{
semaphore.Release();
}
}
public async Task Enqueue(Func<Task> taskGenerator)
{
await semaphore.WaitAsync();
try
{
await taskGenerator();
}
finally
{
semaphore.Release();
}
}
}
And I would queue a task in there like so:
private async Task SaveData()
{
//some code
await taskQueue.Enqueue(async () => { printed = await pm.Print(Template); });
//some code
}
Now what I would like to do is inside the Enqueue method add a log that will contain the info $Print was called with parameter {Template}. How can I get the name of the method executed and it's parameters?
I know I can do [CallerMemberName] string caller = "" to get info that the call was made inside SaveData, but is there an attribute or something to log the info I want?
this is possible (expression trees, etc), but it is incredibly inefficient; perhaps a better approach is to enqueue an object instead, i.e.
abstract class ThingToDo {
public abstract Task DoTheThingAsync();
}
and make your queue a queue of ThingToDo instead of Func<Task<T>>, then you can have things like:
sealed class PrintThing : ThingToDo {
private readonly int x;
private readonly string y;
private readonly string caller;
public PrintThing(int x, string y, [CallerMemberName] string caller = null) {
this.x = x;
this.y = y;
this.caller = caller;
}
public override Task DoTheThingAsync() {...}
public override ToString() => $"{nameof(PrintThing)}, x={x}, y={y} from {caller}";
}
and now you can output the task trivially.
In reality, this isn't all that different to what the compiler would generate anyway for a lambda/anonymous method with captured variables.
I would add the log into the different methods. That way you can also specialize the log messages produced by each method.

Correct way of returning a task in C#

I have a scenario wherein I need to return a method that can be awaited from the caller.
I have here my implementations, and I just want to know which of which is the correct one.
Method 1.
public class ClassA
{
public Task MyTask { get; set; }
public ClassA()
{
MyTask = MyAsyncMethod();
}
private async void MyAsyncMethod()
{
await LongProcessHere();
}
}
public class MyCaller()
{
private async void ExecuteAsync()
{
ClassA ca = new ClassA();
await ca.MyTask;
}
}
Method 2.
public class ClassA
{
public Task MyAsyncMethod()
{
return Task.Run(async()=>
{
await LongProcessHere();
});
}
}
public class MyCaller()
{
private async void ExecuteAsync()
{
ClassA ca = new ClassA();
await ca.MyAsyncMethod();
}
}
If you're asking should I expose a property or method, then that entirely depends on what the Task represents.
If the task is something done once per instance of the class, then having a Task property is appropriate. Usually in this case, the property represents something about the instance, such as "my initialization is complete" or "I am done processing".
If the task is something that you need to do multiple times, then having a Task-returning method is appropriate.
Task-returning methods are vastly more common than Task properties.
On a side note, avoid async void and don't use Task.Run unnecessarily.
The correct code would look like:
public class ClassA
{
// always return a Task from an async method
public async Task MyAsyncMethod()
{
await LongProcessHere();
}
}
public class MyCaller
{
private async Task ExecuteAsync()
{
ClassA ca = new ClassA();
await ca.MyAsyncMethod();
}
}
You do not need to use Task.Run to call an async method. Also async methods should have Task return type as opposed to void. And vice versa.
public class ClassA
{
public async Task MyAsyncMethod()
{
return await LongProcessHere();
}
}
public class MyCaller()
{
private async Task ExecuteAsync()
{
ClassA ca = new ClassA();
await ca.MyAsyncMethod();
}
}

C# 5.0 async await return a list

I'm learning about async/await, and ran into a situation where I need to call an async method
that should return an object or list of same object.
Is this the right way to implement ?
from AManager.cs
public async Task Initialize(string objectPath)
{
AnObject someObject = await BClass.GetAnObject(objectPath);
}
and this is the called method
Class B:
public async Task<AnObject> GetAnObject(string objectPath)
{
AnObject someObj = new AnObject();
return someObj;
}
What happens if I want to return a list of object ? I should create a wrapper that contains a list ? and return that wrapper ?
Because this is not applicable:
public async Task<List<AnObject>> GetAnObject(string objectPath)
To be able to run method as async you need to have await inside. If you won't have it it'll be run as synchronous method. That's probably why it did not work for you. To achieve this you can do something like this:
public async Task<List<string>> GetList()
{
return await Task.Run(() => new List<string>() {"a", "b"});
}
And then to run it:
var list = await GetList()
I am not sure what you are trying accomplish that the Task<List<AnObject>> is not applicable, but here is another example of returning a List of the AnObject in your example above
public class AnObject()
{
SomeProperty {get; set;}
Some Method();
}
public class theCollectionofAnObject : IList<AnObject> ()
{
private List<AnObject> _contents = new List<AnObject>;
//Implement the rest of IList interface
}
//Your async method
public Task<theCollectionofAnObject> GetAnObjects(parameter)
{
}

Categories

Resources