Create Async Wrapper for a NonAsync Method - c#

I am writting a middleware for Asp.Net Identity UserStore where the caller expects a Task and the Method to be called is NonAsynch.
Task IUserSecurityStampStore<T, string>.SetSecurityStampAsync(T user, string stamp)
{
var res = Utility.SetSecurityStamp(user, stamp); // needs to be called as Async
var identityUser = ToIdentityUser(res);
SetApplicationUser(user, identityUser);
return ??? ; // How do i get a task to return here ?
}
How do i return a Task out of res and stamp? Tried Task.FromResult but it says only one type argument is allowed.

Use the async/await pattern.
Wrap the call of the Utility.SetSecurityStamp method into a Task using Task.Run
So your code could become something like that:
async Task IUserSecurityStampStore<T, string>.SetSecurityStampAsync(T user, string stamp)
{
var res = await Task.Run(() => Utility.SetSecurityStamp(user, stamp));
var identityUser = ToIdentityUser(res);
SetApplicationUser(user, identityUser);
}
Or you can just use Task.FromResult to make your method awaitable :
async Task IUserSecurityStampStore<T, string>.SetSecurityStampAsync(T user, string stamp)
{
var res = Utility.SetSecurityStamp(user, stamp);
var identityUser = ToIdentityUser(res);
SetApplicationUser(user, identityUser);
await Task.FromResult(0);
}

Related

How to use await, async and Task in asynchronous programming

This is the first time I'm writing any asynchronous code. I am getting a compile error that says:
Cannot implicitly convert type void to int
while the function is returning an int.
public class Function
{
IAmazonS3 s3client = new AmazonS3Client(RegionEndpoint.USEast1);
public async Task<int> ListS3ObjectsAsync(string bucketName, IAmazonS3 client)
{
ListObjectsRequest request = new ListObjectsRequest();
request.BucketName = bucketName;
ListObjectsResponse response = await client.ListObjectsAsync(request);
do
{
if (response.IsTruncated)
request.Marker = response.NextMarker;
else
request = null;
} while (request != null);
var len = response.S3Objects.Count;
return len;
}
public void FunctionHandler(S3Event evnt, ILambdaContext context)
{
// Here I'm getting the compile error
int x = ListS3ObjectsAsync(evnt.Records?[0].S3.Bucket.Name, s3client).Wait();
}
}
Visual Studio screenshot:
Because ListS3ObjectsAsync method returns a Task<int>, which is an asynchronous representation of getting an int, so in order to get the result, you either need to await the task like this:
int x = await ListS3ObjectsAsync
But that will require you to make the FunctionHandler async aswell.
Or you can call .Result on the task like this
var task = ListS3ObjectsAsync
int x = task.Result
Note that this is a blocking operation and mixing async and non async code is bad practise.
.Wait method only waits for the task to complete, but does not return the Result
You shouldn't block on async code, so the best solution is to use await instead of Wait:
public void FunctionHandler(S3Event evnt, ILambdaContext context)
{
int x = await ListS3ObjectsAsync(evnt.Records?[0].S3.Bucket.Name, s3client);
}
The compiler will then tell you the next part of the solution: FunctionHandler must be made async and its return type changed to Task, i.e.:
public async Task FunctionHandlerAsync(S3Event evnt, ILambdaContext context)
{
int x = await ListS3ObjectsAsync(evnt.Records?[0].S3.Bucket.Name, s3client);
}
The "growth" of async like this is normal.

Task.Run fails to process awaited methods

We are running into a situation where have a requirement to start and execute few launch and forget threads during a call. Though, our call fails to execute if the async methods have any awaited call.
Here is an example. Are we missing something?
public class SomeClass
{
public async Task Test()
{
//Calling synchronously this things works
await Save(1).ConfigureAwait(false);
await Save(2).ConfigureAwait(false);
await Save(3).ConfigureAwait(false);
//Starting three threads at the same time fails while trying to run var queryResult = await SomeClient.QueryAsync<T>(q).ConfigureAwait(false);
_ = Task.Run(async () => await Save(1));
_ = Task.Run(async () => await Save(2));
_ = Task.Run(async () => await Save(3));
}
public async Task<bool> Save(int ct)
{
var x = await Update(ct).ConfigureAwait(false);
return x;
}
public async Task<bool> Update(int ct)
{
await _someObject.CallingSomeAsyncMethod<dynamic>("Some Query").ConfigureAwait(false);
await _someObject.CallingSomeAsyncMethod<dynamic>("Some Query").ConfigureAwait(false);
await _someObject.CallingSomeAsyncMethod<dynamic>("Some Query").ConfigureAwait(false);
return true;
}
}
public class SomeObject
{
public async Task<T> CallingSomeAsyncMethod(string q)
{
await Task.Delay(1000).ConfigureAwait(false);
//OR Any async method which is awaited here just stops the execution
return queryResult;
}
}
If you want to run multiple tasks at the same time you should call the methods without the await and hold the task. Then you can do await Task.WhenAll(task1, task2, task3, ...);

How to get data from Task after running Task.WhenAll(taks)

I have multiple Async methods that I can run one by one but When I Use Task.WhenAll, I really don't know how to get the result. Following are my Async methods
public async Task<IEnumerable<MyModel>> Method1Async()
{
return await Task<IEnumerable<MyModel>>.Run<IEnumerable<MyModel>>(() => GetMethod1Data());
}
//Here Method1Async().Result will get me the data but don't know how to get the result when I am using Task.WhenAll()
public async Task<IEnumerable<MyModel>> Method2Async()
{
return await Task<IEnumerable<MyModel>>.Run<IEnumerable<MyModel>>(() => GetMethod2Data());
}
public async Task<IEnumerable<MyModel>> Method3Async()
{
return await Task<IEnumerable<MyModel>>.Run<IEnumerable<MyModel>>(() => GetMethod3Data());
}
And here is my code where I am using Task.WhenAll
public async Task GetDataAsync()
{
Task[] tasks = new Task[3];
tasks[0] = Method1Async();
tasks[1] = Method2Async();
tasks[2] = Method2Async();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
Now if I call
GetDataAsync()
method, I get all ok but don't know how to get the result from the returned task?
It will return an Array of type IEnumerable<MyModel> so you can set the return type of your async method to that :
public Task<IEnumerable<MyModel>[]> GetDataAsync()
{
Task[] tasks = new Task[3];
tasks[0] = staticDataService.Method1Async();
tasks[1] = staticDataService.Method2Async();
tasks[2] = staticDataService.Method3Async();
return Task.WhenAll(tasks);
}
and then consume it:
IEnumerable<MyModel>[] results = await GetDataAsync();

How to await for without return task method

I am learning about async and await. I have an async method for dialog message and I am doing await to another method.
My code=>
private async Task CalculateProcess()
{
dialogCoordinator = DialogCoordinator.Instance;
// Show...
ProgressDialogController controller = await dialogCoordinator.ShowProgressAsync(this, "HEADER", "MESSAGE");
controller.SetIndeterminate();
// Do your work...
await testing();//I want to await testing method but i cant await testing because testing method no return task
// Close...
await controller.CloseAsync();
}
private void testing()
{
for(int i=0;i<=1000000;i++)
{
}//Looping is example
}
I want to await to testing method but if I want to use await I need to return task from testing.How can I await testing method if I don't have any other returning task?
If you really want to await that method this is the way to go:
private async Task CalculateProcess()
{
dialogCoordinator = DialogCoordinator.Instance;
// Show...
ProgressDialogController controller = await dialogCoordinator.ShowProgressAsync(this, "HEADER", "MESSAGE");
controller.SetIndeterminate();
// Do your work...
await testing();
// Close...
await controller.CloseAsync();
}
private Task testing()
{
for(int i=0;i<=1000000;i++)
{
}//Looping is example
return Task.FromResult(0);
}

Task Error when await in windows store application

Hej, I have a method:
public static async Task<myClassl> GetData()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http:sasa.com");
HttpResponseMessage response = await client.GetAsync("api/GetData");
myClassl data = await response.Content.ReadAsAsync<myClassl>();
return data ;
}
And when I write
myClassl t = await DataGetter.GetData();
I have:
The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
You need to flag your method async where you write:
// Add async to your calling method
private async Task SomeOtherMethod()
{
myClassl t = await DataGetter.GetData();
Any method that uses await internally must be an async method itself.

Categories

Resources