Function as parameter in async method - c#

I call a method containing a function:
public void DoMagicStuff(Func<T> anyfunction) {
// do lots of magic stuff
}
This works:
public void DoNonAsyncStuff() {
DoMagicStuff(()=> {
AnotherFunction();
}
}
While this does not:
public async Task<CustomClass> DoAsynStuff() {
DoMagicStuff(()=> {
return await DoSomethingDifferent();
}
}
"The await operator can only be used in async functions"
How do I make this work for async methods?

If you intend to pass asynchronous delegates to DoMagicStuff, then you need to overload that with an asynchronous version:
public void DoMagicStuff(Func<T> anyfunction)
{
// do lots of magic stuff
T t = anyfunction();
}
public async Task DoMagicStuff(Func<Task> asyncfunction)
{
// do lots of magic stuff
T t = await asyncfunction();
}
This allows you to call await for the asyncfunction.
Any common logic can always be refactored into another method.
With regard to your question, await can only be used in a function that has been declared async, which your lambda hasn't.
It should be like this:
public async Task<CustomClass> DoAsynStuff()
{
await DoMagicStuff(async () =>
{
return await DoSomethingDifferent();
});
}
And in fact, because DoSomethingDifferent already returns a Task, the lambda is superfluous:
public async Task<CustomClass> DoAsynStuff()
{
await DoMagicStuff(DoSomethingDifferent);
}

Related

How to wait for async functions in c#

I have 3 async function that must run together, like this
public async Task Fun1()
{
// do something
}
public async Task Fun2()
{
// do something
}
public async Task Fun2()
{
// do something
}
in my base function I call this functions
this functions must run together
how to wait for this functions until all complete?
public async Task BaseFun()
{
Fun1()
Fun2()
Fun3()
// do something after Fun1, Fun2 and Fun3 complete
}
public async Task BaseFun()
{
await Task.WhenAll(Fun1(),
Fun2(),
Fun3());
// do something after Fun1, Fun2 and Fun3 complete
}
Just add await before the functions.
public async Task BaseFun()
{
await Fun1();
await Fun2();
await Fun3();
// do something after Fun1, Fun2 and Fun3 complete
}
also can do as
public async Task BaseFun()
{
await Fun1();
await Fun2();
await Fun3();
// do something after Fun1, Fun2 and Fun3 complete
}
You can also use Task.WaitAll.
var taskArray = new Task[3]
{
Fun1(),
Fun2(),
Fun3()
};
Task.WaitAll(taskArray);
BTW, why are your Fun1-3 methods also public when you call them through a public base method?

await operator not stopping continuation of other method calls

I have three methods that look like below
private async Task checkPhotoLibraryAccess()
{
PHPhotoLibrary.RequestAuthorization(status =>
{
switch (status)
{
//stuff here
}
}
}
private async Task checkDeviceAuthorizationStatus()
{
var status = AVCaptureDevice.GetAuthorizationStatus(AVMediaType.Video);
switch (status)
{
//stuff here
}
}
private void displayAppBar()
{
AppBar.IsVisible = true;
}
I would like the execution of the first two methods to complete before calling the third. I have researched the issue and have found ways of doing so using the await operator and Wait() method. However my implementations has not worked. Here is my code below.
Attempt 1
private async void MyMethod()
{
await checkPhotoLibraryAccess();
await checkDeviceAuthorizationStatus();
displayAppBar(); //THIS IS CALLED BEFORE COMPLETION OF TWO ABOVE
}
Attempt 2
private async void MyMethod()
{
checkPhotoLibraryAccess().Wait();
checkDeviceAuthorizationStatus().Wait();
displayAppBar(); //SAME ISSUE
}
Any suggestions on how to get this to work?
To get a third method to be executed based on the completion of two other methods you use the WhenAll method of the Task class.
var t1 = CheckPhotoLibraryAccess();
var t2 = CheckDeviceAuthorization();
await Task.WhenAll(t1, t2).ContinueWith(t => DisplayAppBar());
#Yacoub Massad and #SLaks reminded me that in order for await to work on a method call, the method needs to contain an await operator.
So I changed my PhotoLibraryAccess method to contain an await operator and placed its method call right before the DisplayAppBar call.
private async Task checkPhotoLibraryAccess()
{
var status = await PHPhotoLibrary.RequestAuthorizationAsync();
//stuff here
}
And then ...
private async void MyMethod()
{
checkDeviceAuthorizationStatus(); //Removed async Task stuff
await checkPhotoLibraryAccess();
displayButtons(); //IT WORKS
}

window phone - method is not run ?

I create a method in class :
public async void Foo()
{
.....
string response = await Utilities.sendData(data);
....
}
I create break point and run,when it call foo method,but break point run at
string response = await Utilities.sendData(data)
and then break point is disappear,if i call in code behind (xaml)it no problem
You can call an async method from synchronous code.
The async modifier says that the code within that method can await on other async methods. Here's a silly example
public class Foo
{
public void DoSomething()
{
await Something(); //invalid
Something(); //valid
}
public async void Something()
{
await SomethingElse(); //valid
SomethingElse(); // also valid, but synchronous
}
public async void SomethingElse()
{
}
}

Making interface implementations async

I’m currently trying to make my application using some Async methods.
All my IO is done through explicit implementations of an interface and I am a bit confused about how to make the operations async.
As I see things I have two options in the implementation:
interface IIO
{
void DoOperation();
}
OPTION1:
Do an implicit implementation async and await the result in the implicit implementation.
class IOImplementation : IIO
{
async void DoOperation()
{
await Task.Factory.StartNew(() =>
{
//WRITING A FILE OR SOME SUCH THINGAMAGIG
});
}
#region IIO Members
void IIO.DoOperation()
{
DoOperation();
}
#endregion
}
OPTION2:
Do the explicit implementation async and await the task from the implicit implementation.
class IOAsyncImplementation : IIO
{
private Task DoOperationAsync()
{
return new Task(() =>
{
//DO ALL THE HEAVY LIFTING!!!
});
}
#region IIOAsync Members
async void IIO.DoOperation()
{
await DoOperationAsync();
}
#endregion
}
Are one of these implementations better than the other or is there another way to go that I am not thinking of?
Neither of these options is correct. You're trying to implement a synchronous interface asynchronously. Don't do that. The problem is that when DoOperation() returns, the operation won't be complete yet. Worse, if an exception happens during the operation (which is very common with IO operations), the user won't have a chance to deal with that exception.
What you need to do is to modify the interface, so that it is asynchronous:
interface IIO
{
Task DoOperationAsync(); // note: no async here
}
class IOImplementation : IIO
{
public async Task DoOperationAsync()
{
// perform the operation here
}
}
This way, the user will see that the operation is async and they will be able to await it. This also pretty much forces the users of your code to switch to async, but that's unavoidable.
Also, I assume using StartNew() in your implementation is just an example, you shouldn't need that to implement asynchronous IO. (And new Task() is even worse, that won't even work, because you don't Start() the Task.)
Better solution is to introduce another interface for async operations. New interface must inherit from original interface.
Example:
interface IIO
{
void DoOperation();
}
interface IIOAsync : IIO
{
Task DoOperationAsync();
}
class ClsAsync : IIOAsync
{
public void DoOperation()
{
DoOperationAsync().GetAwaiter().GetResult();
}
public async Task DoOperationAsync()
{
//just an async code demo
await Task.Delay(1000);
}
}
class Program
{
static void Main(string[] args)
{
IIOAsync asAsync = new ClsAsync();
IIO asSync = asAsync;
Console.WriteLine(DateTime.Now.Second);
asAsync.DoOperation();
Console.WriteLine("After call to sync func using Async iface: {0}",
DateTime.Now.Second);
asAsync.DoOperationAsync().GetAwaiter().GetResult();
Console.WriteLine("After call to async func using Async iface: {0}",
DateTime.Now.Second);
asSync.DoOperation();
Console.WriteLine("After call to sync func using Sync iface: {0}",
DateTime.Now.Second);
Console.ReadKey(true);
}
}
P.S.
Redesign your async operations so they return Task instead of void, unless you really must return void.
I created a sample app based on Svick's answer and found that calling IOImplementation.DoOperationAsync() without the async keyword does not result in a compiler/Visual Studio warning. This was based on Visual Studio 2019 and .NET Core 3.1.
Sample code below.
public interface ISomething
{
Task DoSomethingAsync();
}
public class Something : ISomething
{
public async Task DoSomethingAsync()
{
await Task.Run(() => Thread.Sleep(2000));
Console.WriteLine("Message from DoSomethingAsync");
throw new Exception("Some exception");
}
}
class Program
{
static void Main(string[] args)
{
ISomething something = new Something();
Console.WriteLine("pre something.DoSomethingAsync() without await");
something.DoSomethingAsync(); // No compiler warning for missing "await" and exception is "swallowed"
Console.WriteLine("post something.DoSomethingAsync() without await");
Thread.Sleep(3000);
// Output:
// pre something.DoSomethingAsync() without await
// post something.DoSomethingAsync() without await
// Message from DoSomethingAsync
}
}
An abstract class can be used instead of an interface (in C# 7.3).
// Like interface
abstract class IIO
{
public virtual async Task<string> DoOperation(string Name)
{
throw new NotImplementedException(); // throwing exception
// return await Task.Run(() => { return ""; }); // or empty do
}
}
// Implementation
class IOImplementation : IIO
{
public override async Task<string> DoOperation(string Name)
{
return await await Task.Run(() =>
{
if(Name == "Spiderman")
return "ok";
return "cancel";
});
}
}

c# Can a "task method" also be an "async" method?

I'm trying to get the hand of the new async CTP stuff and I'm probably confusing myself here..
I can have this "task method", with no problem:
public static Task<String> LongTaskAAsync() {
return Task.Run(() => {
return("AAA");
});
}
But what if I need the task to execute another task, can I mark it as "async" and use "await"? I tried this:
public async static Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return Task.Run(() => {
return("AAA");
});
}
But then mysteriously get this compiler error: Since this is an async method, the return expression must be of type 'string' rather than Task<string>
What am I missing here?
You may want to read my async/await intro post.
Return values from async methods are wrapped in a Task<TResult>. Likewise, await unwraps those return values:
public static async Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return await Task.Run(() => {
return("AAA");
});
}
The reasoning behind this is described in my Async "Why Do the Keywords Work That Way" Unofficial FAQ.
P.S. You can also use Task.FromResult for simple tests like this.
Edit: If you want to create and return the Task object itself, then the method should not be async. One somewhat common pattern is to have a public non-async method that calls the async portion only if necessary.
For example, some kind of asynchronous cache - if the object is in the cache, then return it immediately; otherwise, asynchronously create it, add it to the cache, and return it (this is example code - not thread-safe):
public static Task<MyClass> GetAsync(int key)
{
if (cache.Contains(key))
return Task.FromResult(cache[key]);
return CreateAndAddAsync(key);
}
private static async Task<MyClass> CreateAndAddAsync(int key)
{
var result = await CreateAsync(key);
cache.Add(key, result);
return result;
}
Can a “task method” also be an “async” method?
Yes it can be, by simply changing the method signature to public async static Task<Task<String>> LongTaskAAsync() since that is, what it will return.
If you use the async keyword, the runtime will wrap the type you return into a task, to enable asynchronousness. Say if you return a string, the runtime will wrap that into a Task<string>. int will go Task<int> and Task<string> will go Task<Task<string>>. See this console app to clearify:
public class Program
{
public static void Main(string[] args)
{
// start the main procedure asynchron
Task.Run(() => DoIt()).Wait();
}
// for async support since the static main method can't be async
public static async void DoIt()
{
Program p = new Program();
// use the methods
string s = await p.GetString();
int i = await p.GetInt();
Task<string> tsk = await p.GetTaskOfString();
// just to prove the task works:
// C# 5
string resultFromReturnedTask = await tsk;
// C# 4
string resultFromReturnedTask2 = tsk.Result;
}
public async Task<string> GetString()
{
return "string";
}
public async Task<int> GetInt()
{
return 6;
}
public async Task<Task<string>> GetTaskOfString()
{
return Task.Run(() => "string");
}
}

Categories