I have a method shown bellow
static public async Task GetStudentDetails(studentinfo stu)
{
// here i am using webservice call
// do some other operations
}
and this method is called from another method as shown below:
static public void GetUIWindow((int a, int b)
{
someanothercall();
studentinfo s = new Studentinfo();
GetStudentDetails(s); // here how can i use await keyword ??
}
Here how can i use await keyword ??
how can i use await keyword ??
You await the task returned from GetStudentDetails:
await GetStudentDetails(s);
The compiler will then complain at you saying that you should change GetUIWindow to be async and return a Task. So go ahead and do that:
static public async Task GetUIWindowAsync(int a, int b)
Then do the same for all the places that call GetUIWindow. Rinse and repeat; it's async all the way.
Related
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
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();
}
}
I have a problem with understanding of execution of asynchronously method which is passed as a parameter to StartNew method of TaskFactory. Could you explain me how exactly it will work?
I have UserInfo class which contains user identifier.
public sealed class UserInfo
{
[ThreadStatic]
public static Guid UserId;
}
I have my custom implementation of TaskScheduler. I don't show a full code of this class because it isn't interesting. This class set user identifier to current thread. Set user identifier to UserId variable.
public sealed class CustomTaskScheduler : TaskScheduler
{
// Sets user information to the variable which is marked ThreadStatisAttribute.
}
I created my custom TaskFactory which takes custom scheduler as a parameter of constructor.
public sealed class CustomTaskFactory : TaskFactory
{
public CustomTaskFactory(CustomTaskScheduler taskScheduler) : base(taskScheduler) { }
}
And finally I have the Service class which performs asynchronously operations.
public sealed class Service
{
private readonly CustomTaskScheduler customTaskScheduler;
private readonly CustomTaskFactory customTaskFactory;
private readonly SomeClient someClient;
public Service()
{
this.customTaskScheduler = new CustomTaskScheduler();
this.customTaskFactory = new CustomTaskFactory(this.customTaskScheduler);
this.someClient = new SomeClient();
}
public void DoSomething(string param)
{
this.customTaskFactory.StartNew(() => testAsync(param)).Unwrap().Wait();
// This method will use the result which is given by async operation which is called above.
DoSomethingElseSynchronously();
}
private async Task DoSomethingAsync()
{
Thread.Sleep(1000);
int result1 = await this.customTaskFactory.StartNew(() => PerformAsyncOperation(default(int))).Unwrap();
Thread.Sleep(1000);
int result2 = await this.customTaskFactory.StartNew(() => PerformAsyncOperation(default(int))).Unwrap();
int sum = result1 + result2;
}
private async Task<int> PerformAsyncOperation(int x)
{
Thread.Sleep(1000);
return await this.customTaskFactory.StartNew(() => CallClientAsync(x)).Unwrap();
}
private async Task<int> CallClientAsync(int x)
{
Thread.Sleep(1000);
int resultObtainedFromClient1 = await this.customTaskFactory.StartNew(async () => await this.someClient.GetAsync(x)).Unwrap();
Thread.Sleep(1000);
int resultObtainedFromClient2 = await this.customTaskFactory.StartNew(async () => await this.someClient.GetAsync(x)).Unwrap();
int result = resultObtainedFromClient1 + resultObtainedFromClient2;
return result;
}
}
Well, to be fair, I have two questions:
What is the difference between calls await this.customTaskFactory.StartNew(async () => await this.someClient.GetAsync(x)).Unwrap() and await this.customTaskFactory.StartNew(() => this.someClient.GetAsync(x)).Unwrap() I would like to recall that I am interested in my ThreadStatic variable UserId. As I understand the first call will be executed in the same thread which called StartNew method and my thread static field will be filled in this case. In the second call I puts asynchronous method as a parameter of StartNew method. That means that task will contain asynchronous method which maybe will be executed by another thread and this another thread will not contain my UserId variable.
I need to be sure that each thread will contain not empty UserId variable. Are there any cases when I lose UserId data? How to prevent it?
Thanks in advance
With the addition of async / await to TypeScript using Promise(s) can look very syntactically close to Task(s).
Example:
Promise (TS)
public async myAsyncFun(): Promise<T> {
let value: T = await ...
return value;
}
Task (C#)
public async Task<T> MyAsyncFun() {
T value = await ...
return value;
}
I was wondering if the other way around, there was an equivalent to .then() for Task(s).
Example:
Promise (TS)
Promise<T> promise = ...
promise.then((result: T) => ...do something...);
I've used ContinueWith which can work if you have one or multiple Tasks running.
example:
public async Task<T> MyAsyncFun() {
T value = await ...
return value;
}
MyAsyncFun().ContinueWith(...
https://msdn.microsoft.com/en-us/library/dd270696(v=vs.110).aspx
You can create a handy extension method for task continuations to match the javascript .then function. I find it easier to use than .ContinueWith, which has its own set of pitfalls and encumbrances.
public static class TaskExtensions
{
public static async Task<TV> Then<T,TV>(this Task<T> task, Func<T,TV> then)
{
var result = await task;
return then(result);
}
}
Then you can use it like so
Task<User> userRecord = GetUserById(123)
Task<string> firstName = userRecord.Then(u => u.FirstName)
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