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";
});
}
}
Related
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);
}
I try to wait for the class to be finished with instantiate.
My architecture is the following. Cook is inheriade from CookChief.
And if I instantiate cook, CookChief is creating himself, but CookChief is calling 1 other class named Cookhelper the cookhelper is waiting for a input and for this input method i want to wait in Cook.
The thing is iam creating this in MVVM Galasoft and my entry point is the CookViewmodel, with a relaycommand.
In the code below you can see my architecture. To say it short I want to wait until this bool processed = await Task.Run(() => ValidateForDeviceId()); is finished.
My first step was to outsource the constructer of each class. And create a init method.
This is my code:
public CookViewModel()
{
startCookButtonCommand = new RelayCommand(Cook);
}
private async Task Cook()
{
cook.Init();
}
public class Cook : CookChief
{
public Cook()
{
}
public async Task Init()
{
await this.CookChiefInit();
//here I want to wait until CookChiefInit is finished
Cooking();
}
public void Cooking()
{
MessageBox.Show("Input received");
}
}
Now the Cookchief:
public Cookchief()
{
}
protected async Task CookchiefInit()
{
this.Cookhelper = new Cookhelper();
Cookhelper.CookHelperInit();
}
And in the CookHelper we do this:
public CookHelper()
{
}
public void CookHelperInit()
{
this.driverWindow = new DriverWindow();
startProc();
}
private async void startProc()
{
ShowOrCloseDriverWindow(true);
//this is the task what we wait for before we can repeat
bool processed = await Task.Run(() => ValidateForDeviceId());
if(processed)
{
ShowOrCloseDriverWindow(false);
}
else
{
MessageBox.Show("DriverError");
}
}
private bool ValidateForDeviceId()
{
for (; ; )
{
this.deviceId = Input.deviceId;
if (deviceId > 0)
{
break;
}
}
return true;
}
Per the discussion in the comments, the problem here was that the initialization routine mixed synchronous and asynchronous methods and calls. Additionally, some async methods were called without the await keyword. The solution was to make all calls asynchronous and await them.
cook.Init() needs an await:
private async Task Cook()
{
await cook.Init();
}
In CookchiefInit(), the CookHelperInit() call needs to be awaited:
protected async Task CookchiefInit()
{
this.Cookhelper = new Cookhelper();
Cookhelper.CookHelperInit();
}
In order to await CookHelperInit(), it needs to be made asynchronous. The startProc() call is to an async method, so it must also be awaited:
public async Task CookHelperInit()
{
this.driverWindow = new DriverWindow();
await startProc();
}
Looking for help after searching has not produced a good suggestion.
I always avoid having async void methods in code. I don't use event handlers. Sometimes a vendor or library gives you no choice, and their methods are implemented as async void.
If my method itself returns Task, but i have no choice but to call a 3rd party library method with async void, is there a way to safely wrap their method in such a way that I can keep my code free of the async void dangers, as listed here about terminating my process?
StackOverflow - why is async void bad
An example of my concern is as follows:
3rd party library method looks like this
public async void GetSomethingFromAService()
{
/// their implementation, and somewhere along the way it throws an exception, in this async void method --- yuck for me
}
My method say on a service controller:
public async Task<bool> MyMethod()
{
await ThirdPartyLibrary.GetSomethingFromAService();
return await Task.FromResult(true);
}
My method is fine except the 3rd party library is async void and throws an exception. My app is going to die. I don't want it to because my code is well written an not async void. But I can't control their code. Can i wrap the call to their async void method in such a way to protect my code from dying?
It's tricky and it might not work for all scenarios, but it may be possible to track the life-time of an async void method, by starting its execution on a custom synchronization context. In this case, SynchronizationContext.OperationStarted / SynchronizationContext.OperationCompleted will be called upon start and end of the asynchronous void method, correspondingly.
In case an exception is thrown inside an async void method, it will be caught and re-thrown via SynchronizationContext.Post. Thus, it's also possible to collect all exceptions.
Below is an a complete console app example illustrating this approach, loosely based on Stephen Toub's AsyncPump (warning: only slightly tested):
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncVoidTest
{
class Program
{
static async void GetSomethingFromAService()
{
await Task.Delay(2000);
throw new InvalidOperationException(nameof(GetSomethingFromAService));
}
static async Task<int> MyMethodAsync()
{
// call an ill-designed 3rd party async void method
// and await its completion
var pump = new PumpingContext();
var startingTask = pump.Run(GetSomethingFromAService);
await Task.WhenAll(startingTask, pump.CompletionTask);
return 42;
}
static async Task Main(string[] args)
{
try
{
await MyMethodAsync();
}
catch (Exception ex)
{
// this will catch the exception thrown from GetSomethingFromAService
Console.WriteLine(ex);
}
}
}
/// <summary>
/// PumpingContext, based on Stephen Toub's AsyncPump
/// https://blogs.msdn.com/b/pfxteam/archive/2012/02/02/await-synchronizationcontext-and-console-apps-part-3.aspx
/// https://stackoverflow.com/q/49921403/1768303
/// </summary>
internal class PumpingContext : SynchronizationContext
{
private int _pendingOps = 0;
private readonly BlockingCollection<ValueTuple<SendOrPostCallback, object>> _callbacks =
new BlockingCollection<ValueTuple<SendOrPostCallback, object>>();
private readonly List<Exception> _exceptions = new List<Exception>();
private TaskScheduler TaskScheduler { get; }
public Task CompletionTask { get; }
public PumpingContext(CancellationToken token = default(CancellationToken))
{
var taskSchedulerTcs = new TaskCompletionSource<TaskScheduler>();
this.CompletionTask = Task.Run(() =>
{
SynchronizationContext.SetSynchronizationContext(this);
taskSchedulerTcs.SetResult(TaskScheduler.FromCurrentSynchronizationContext());
try
{
// run a short-lived callback pumping loop on a pool thread
foreach (var callback in _callbacks.GetConsumingEnumerable(token))
{
try
{
callback.Item1.Invoke(callback.Item2);
}
catch (Exception ex)
{
_exceptions.Add(ex);
}
}
}
catch (Exception ex)
{
_exceptions.Add(ex);
}
finally
{
SynchronizationContext.SetSynchronizationContext(null);
}
if (_exceptions.Any())
{
throw new AggregateException(_exceptions);
}
}, token);
this.TaskScheduler = taskSchedulerTcs.Task.GetAwaiter().GetResult();
}
public Task Run(
Action voidFunc,
CancellationToken token = default(CancellationToken))
{
return Task.Factory.StartNew(() =>
{
OperationStarted();
try
{
voidFunc();
}
finally
{
OperationCompleted();
}
}, token, TaskCreationOptions.None, this.TaskScheduler);
}
public Task<TResult> Run<TResult>(
Func<Task<TResult>> taskFunc,
CancellationToken token = default(CancellationToken))
{
return Task.Factory.StartNew<Task<TResult>>(async () =>
{
OperationStarted();
try
{
return await taskFunc();
}
finally
{
OperationCompleted();
}
}, token, TaskCreationOptions.None, this.TaskScheduler).Unwrap();
}
// SynchronizationContext methods
public override SynchronizationContext CreateCopy()
{
return this;
}
public override void OperationStarted()
{
// called when async void method is invoked
Interlocked.Increment(ref _pendingOps);
}
public override void OperationCompleted()
{
// called when async void method completes
if (Interlocked.Decrement(ref _pendingOps) == 0)
{
_callbacks.CompleteAdding();
}
}
public override void Post(SendOrPostCallback d, object state)
{
_callbacks.Add((d, state));
}
public override void Send(SendOrPostCallback d, object state)
{
throw new NotImplementedException(nameof(Send));
}
}
}
I am very new to the async/await usage. I am trying to abstract the asynchrony and await conditionally in the UI. I have an abstract base class:
public abstract class Base
{
public abstract bool IsRunning { get; }
public abstract Task<bool> Run();
}
and from it some derived instances, first one being synchronous:
internal class Derived1 : Base
{
private readonly Base baseCase;
private Task<bool> task;
public Derived1(Base baseCase)
{
this.baseCase = baseCase;
}
public override bool IsRunning
{
get { return false; }
}
public override Task<bool> Run()
{
task = new Task<bool>(() =>
{
bool ok = DoSomething();
return ok;
});
return task;
}
}
and a derived class for an asynchronous implementation:
internal class Derived2 : Base
{
private readonly Base baseCase;
private Task<bool> task;
public Derived2(Base baseCase)
{
this.baseCase = baseCase;
}
public override bool IsRunning
{
get { return task != null && task.Status == TaskStatus.Running; }
}
public override Task<bool> Run()
{
task = new Task<bool>(() =>
{
bool ok = DoSomething();
return ok;
});
return task;
}
}
Then in the UI, I would like to await on asynchronous task (if user specified so in a run-time config), as follows:
internal class CaseMenuHandler
{
private async void OnRun(object sender, EventArgs args)
{
foreach (var case in Cases)
{
Base baseCaseRunner = GetCaseRunner(case);
try
{
bool ok = true;
if( something_holds ) {
ok = await baseCaseRunner.Run();
}
else {
ok = baseCaseRunner.Run().Result;
}
}
catch (Exception e)
{
LogError(...);
}
}
}
Hope this is clear. Can I do the above, specifically awaiting conditionally inside an if block? Ideally I would like to make the Base class only return bool and not Task<bool> for the Run method, and only have the Derived2 class override to return a Task<bool>, but I am not clear on how to do that. Perhaps I should return the task.Result inside the Run method of Derived2? If there's a better way to this including the abstraction or any other corrections, please let me know. Appreciate any ideas.
EDIT #1
The Run method form for the synchronous implementation in Derived1 has been clarified in the responses below. I am not allowed to change the signature of the DoSomething method though, so given that, my Run method in Derived2 (asynchronous implementation) looks as follows now (thanks to #Stripling's comments):
public override async Task<bool> Run()
{
task = new Task<bool>(() =>
{
bool ok = DoSomething();
return ok;
});
task.Start();
return await task;
}
EDIT #2:
When I try the above (also tried putting a task.Start() call after the task definition, I get the following error:
Cross-thread operation not valid: Application accessed domain object from a thread other than a legal thread.
Can I do the above, specifically awaiting conditionally inside an if block?
You can, but you shouldn't have to. If you do things right, there's no great advantage to specifically invoking a synchronous task in a blocking fashion: as a general rule, you can just await the Task that's returned, and if it represents a synchronous task then the await will be resolved synchronously with very little overhead.
When I say "if you do things right", here's the right way:
// synchronous
public override Task<bool> Run()
{
var result = DoSomething();
return Task.FromResult(result);
}
// asynchronous
public override async Task<bool> Run()
{
var result = await DoSomethingAsync();
return result;
}
awaiting the result of the first example above will not do any thread-switching or anything like that. awaiting the result of the second might, depending on the implementation of DoSomethingAsync(). There's no particular need for a layer of abstraction: you can always check a Task to whether it's completed or not, and awaiting an already-completed task will always return a value immediately.
I don't see how your synchronous version is synchronous, you still use the Task.Run(, I would have expected
internal class Derived1 : Base
{
private readonly Base baseCase;
private Task<bool> task;
public Derived1(Base baseCase)
{
this.baseCase = baseCase;
}
public override bool IsRunning
{
get { return false; }
}
public override Task<bool> Run()
{
bool ok = DoSomething();
return Task.FromResult(ok);
}
}
If you do it that way instead of the way you are doing it, your other code just becomes
private async void OnRun(object sender, EventArgs args)
{
foreach (var case in Cases)
{
Base baseCaseRunner = GetCaseRunner(case);
try
{
bool ok = true;
ok = await baseCaseRunner.Run();
}
catch (Exception e)
{
LogError(...);
}
}
}
The asynchronous version will run asynchronously and the synchronous version will run synchronously.
Your "async version" is not really async either, see Stripling's answer for the correct way to do that method.
Then in the UI, I would like to await on asynchronous task (if user specified so in a run-time config)
First off, I just have to say that this is a really bad idea. Some things should be configurable, and some should not. The asynchrony of operations should not be configurable. Period. This is a horrible design, and the first thing I would do is push back hard against ridiculous "requirements" like this. It literally makes the same amount of sense as a configurable flag for whether or not to throw exceptions.
That said, it can be done. It's painful, difficult to maintain, and completely useless at the end of the day. But hey, I assume you're getting paid for this so it's all good, eh?
If you must do this for political reasons (there are absolutely no valid technical reasons), then I recommend you use the Boolean Argument Hack from my article on brownfield async. One problem with just blocking (Result) is that it doesn't work if Run uses await (for reasons described on my blog).
The boolean argument hack simply adds a boolean argument indicating whether the method is expected to complete synchronously or not.
public abstract class Base
{
public abstract Task<bool> RunAsync(bool sync);
}
The semantics here are that if sync is true, then the task returned from RunAsync must already be completed.
Your implementation then looks like:
internal class Derived1 : Base
{
public override async Task<bool> RunAsync(bool sync)
{
IsRunning = true;
try
{
if (sync)
return DoSomething();
return await Task.Run(() => DoSomething());
}
finally
{
IsRunning = false;
}
}
}
And it's called like:
private async void OnRun(object sender, EventArgs args)
{
foreach (var case in Cases)
{
Base baseCaseRunner = GetCaseRunner(case);
try
{
bool sync = !something_holds;
bool ok = await baseCaseRunner.RunAsync(sync);
}
catch (Exception e)
{
LogError(...);
}
}
}
Note that it can always be called with await, but OnRun will actually be synchronous if sync is true. This is due to the "await fast path" - the fact that await first checks whether the task is already complete, and if it is, it continues synchronously (as described in my async intro blog post).
Use Task.FromResult to return a task that contains the result that was computed synchronously, and await.
bool ok = DoSomething();
return Task.FromResult(ok);
As a side note I'd not put synchronous code in a method that was generally intended to be asynchronous (or that is synchronous in other classes/places) and vice versa. I'd use different interfaces/base classes for a synchronous and an asynchronous implementation.
interface IRunnable
{
bool IsRunning;
bool Run();
}
interface IRunnableAsync
{
bool IsRunning;
Task<bool> RunAsync();
}
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()
{
}
}