This question already has answers here:
How to cancel a Task in await?
(4 answers)
Closed 2 years ago.
As far as I understand, when you want to wait until async method is completed, you have to use await. Otherwise, it's thread will be detached and you'll never hear back from it again. But when you use await, you then have to make the enclosing method async as well (Why though?). That means, you have to use async-await all the way up the call stack. That also means, you can't await-async in constructors.
async Task<int> Boo()
{
return 1;
}
async Task Far()
{
int res = await Boo();
}
Is there a way to stop this infestation? Meaning, how to execute Boo synchronously and get the result, without having to make Far async ?
EDIT:
Does this answer your question? How to cancel a Task in await?
No, I need to get task done, not cancel it.
That also means, you can't await-async in constructors. - why would you want to?
I really don't, but it looks like I have to.
Task.Result is only the answer if you like deadlocks. Why are you trying so hard to avoid async/await?
the project is huge
for some external methods there are no reason to run them async, though they declared as such
using results of async operations in constructors
"you then have to make the enclosing method async as well" - no. you can wait for the result synchronously by accessing Task.Result
Using Task.Result looks like the answer, but right now I'm unable to compile with it. Supposedly, RunSynchronously() should also be able to solve problem?
because you don't want half-baked objects if you can help it.
Sure, I don't. Ideally, I want to synchronously get the result of external method, marked async and finish object initialization.
Don't do work in constructors
Good point, but I just can't help myself.
RESOLUTION:
Seems like .GetAwaiter().GetResult(); was just enough to do the trick for me. I would consider this an answer, if the question was not marked duplicate.
I think it's a better to approach to use a static method that plays the role of a factory that create instances of your class in an async fashion using a private constructor:
Let me illustrate that using some code
public class MyWorker
{
public IList<TData> Data { get; set; }
//static async method that behave like a constructor
async public static Task<MyWorker> CreateAsync()
{
var data= await FetchDataAsync();
return new MyWorker(data);
}
// private constructor called by the async method
private MyWorker (IList<TData> data)
{
this.Data = data;
}
}
//..
var worker = await MyWorker.CreateAsync();
this way is less error-prone since you instantiate your class in one line of code (LOC) and you don't need to do that using 2 LOC (one for the instance, one for calling the async method which you or someone else might forget to call).
Related
This question already has answers here:
Wraping sync API into Async method
(2 answers)
Write a well designed async / non-async API
(3 answers)
Using async await when implementing a library with both synchronous and asynchronous API for the same functionality
(2 answers)
How to safely mix sync and async code? [duplicate]
(2 answers)
Closed 1 year ago.
I'm still learning async/await concepts so please bear with me. Suppose there is this legacy code that defines a contract for getting data from a data source (local database in the real case):
public interface IRepository<T> {
IList<T> GetAll();
}
In new code I have the following interface:
public interface IMyObjectRepository {
Task<IEnumerable<MyObject>> GetAllAsync();
}
The MyObjectRepository class depends on IRepository<T> like this:
public class MyObjectRepository : IMyObjectRepository
{
private readonly IRepository<Some.Other.Namespace.MyObject> repo_;
private readonly IDataMapper<Some.Other.Namespace.MyObject, MyObject> mapper_;
public BannerRepository(IRepository<Some.Other.Namespace.MyObject> repo, IDataMapper<Some.Other.Namespace.MyObject, MyObject> mapper)
{
repo_ = repo;
mapper_ = mapper;
}
}
How do I implement the IMyObjectRepository.GetAllAsync() method in such a way that it makes sense in the context of asynchronous programming? Getting data from some local data source is an I/O bound operation, so the way I did it is:
public async Task<IEnumerable<MyObject>> GetAllAsync()
{
var tcs = new TaskCompletionSource<IEnumerable<MyObject>>();
try
{
GetAll(objects =>
{
var result = new List<MyObject>();
foreach (var o in objects)
{
result.Add(mapper_.Map(o));
}
tcs.SetResult(result);
});
}
catch (Exception e)
{
tcs.SetException(e);
}
return await tcs.Task;
}
private void GetAll(Action<IEnumerable<Some.Other.Namespace.MyObject>> handle)
{
IEnumerable<Some.Other.Namespace.MyObject> objects = repo_.GetAll<Some.Other.Namespace.MyObject>();
if (objects is null)
{
objects = Enumerable.Empty<Some.Other.Namespace.MyObject>();
}
handle(objects);
}
Does this make any sense? I did not want to use Task.Run() because, the way I understand it, that wastes a thread for nothing in the case of an I/O bound operation which makes sense.
Do not implement a synchronous method with an asynchronous implementation. Also do not implement a fake-asynchronous method (an asynchronous method that just runs synchronous code on a thread pool thread). Instead, first take a step back...
How do I implement the IMyObjectRepository.GetAllAsync() method in such a way that it makes sense in the context of asynchronous programming?
Wrong question.
Instead of approaching async by saying "how do I make this async", approach it from the other end. Start with things that should be async. As you noted, I/O is perfect for async code. So start with the code that actually does the I/O - the lowest-level method. This could be IRepository<T>.GetAll - whatever actually does the communication with the database. Change that to call the async equivalent with await, and allow async to grow from the lowest-level method out to the rest of your code.
The approach in the example is a valid one. I would however be careful to only use it when absolutely needed, since users might get very confused when calling the "async" method, only for it to block. In that sense it might be preferable to use Task.Run() since that will not block. But it does require the called code to be threadsafe.
In your example there is no point in using async, just remove that and the await should give the exact same result, since you are returning a task anyway.
Using Task.FromResult is another easy alternative. But it will not be quite identical if exception occurs. Using a TaskCompletionSource and .SetException will make exceptions occur as a property of the Task.Exception rather than raised from the method call itself. If the task is awaited it should not matter, since both cases should be handled by a try/catch. But there are other ways to handle exceptions for tasks, so you need to be aware how it is used, and provide appropriate documentation/comments to describe the behavior.
I have a large scale C# solution with 40-ish modules.
I'm trying to convert a service used solution-wide from synchronous to asynchronous.
the problem is I can't find a way to do so without changing the signature of the method.
I've tried wrapping said asynchronous desired operation with Task but that requires changing the method signature.
I've tried changing the caller to block itself while the method is operating but that screwed my system pretty good because it's a very long calling-chain and changing each of the members in the chain to block itself is a serious issue.
public SomeClass Foo()
{
// Synchronous Code
}
Turn this into:
public SomeClass Foo()
{
//Asynchronous code
}
whilst all callers stay the same
public void DifferentModule()
{
var class = Foo();
}
Any implementation that fundamentally changes something from sync to async is going to involve a signature change. Any other approach is simply not going to work well. Fundamentally: async and sync demand different APIs, which means: different signatures. This is unavoidable, and frankly "How to convert synchronous method to asynchronous without changing it's signature?" is an unsolvable problem (and more probably: the wrong question). I'm sorry if it seems like I'm not answering the question there, but... sometimes the answer is "you can't, and anyone who says you can is tempting you down a very bad path".
In the async/Task<T> sense, the most common way to do this without breaking compatibility is to add a new / separate method, so you have
SomeReturnType Foo();
and
Task<SomeReturnType> FooAsync(); // or ValueTask<T> if often actually synchoronous
nothing that Foo and FooAsync here probably have similar but different implementations - one designed to exploit async, one that works purely synchronously. It is not a good idea to spoof one by calling the other - both "sync over async" (the synchronous version calling the async version) and "async over sync" (the async version calling the sync version) are anti-patterns, and should be avoided (the first is much more harmful than the second).
If you really don't want to do this, you could also do things like adding a FooCompleted callback event (or similar), but : this is still fundamentally a signature change, and the caller will still have to use the API differently. By the time you've done that - you might as well have made it easy for the consumer by adding the Task<T> API instead.
The common pattern is to add an Async to the method name and wrap the return type in a Task. So:
public SomeClass Foo()
{
// Synchronous Code
}
becomes:
public Task<SomeClass> FooAsync()
{
// Asynchronous Code
}
You'll end up with two versions of the method, but it will allow you to gradually migrate your code over to the async approach, and it won't break the existing code whilst you're doing the migration.
If you desperately need to do this, it can be achieved by wrapping the Synchronous code that needs to become Asynchronous in a Task this can be done like this:
public SomeClass Foo()
{
Task t = Task.Run(() =>
{
// Do stuff, code in here will run asynchronously
}
t.Wait();
// or if you need a return value: var result = t.Wait();
return someClass;
// or return result
}
Code you write inside the Task.Run(() => ...) will run asynchronously
Short explanation: with Task t = Task.Run(() => ...) we start a new Task, the "weird" parameter is a Lambda expression, basically we're passing a anonymous Method into the Run method which will get executed by the Task
We then wait for the task to finish with t.Wait();. The Wait method can return a value, you can return a value from an anonymous method just like from any method, with the return keyword
Note: This can, but should not be done. See Sean's answer for more
I've been reading about asynchronous methods, specifically in C# with the new async/await keywords, and despite much reading and perusing this forum, I still am convinced that async requires multithreading. Please explain what I am misunderstanding!
I understand that you can write an async method without spawning a background thread. Super basic example:
async System.Threading.Tasks.Task<int> GetZeroAsync()
{
return 0;
}
But of course, this method is completely useless to be marked as async because, well, it isn't asynchronous. I also get a compiler warning about the method lacking an "await" operator, as expected. Okay, so what can we await? I can await something like Task.Run(), but that defeats the point, because I'm now using multithreading. Any other example I've found online tries to prove that you don't need multithreading by simply doing something like so:
async System.Threading.Tasks.Task<int> MyMethodAsync()
{
return await CallAnotherAsyncMethod();
}
Maybe I'm misunderstanding this, but all it proves to me is that I'm not the one who starts the multithreaded task, but I'm just calling another method that does. Since CallAnotherAsyncMethod() is also an async method, it must follow the exact same rules, right?. I can't have every async method just await another async sub-method forever, at some point it must stop unless you want infinite recursion.
The way I currently understand it, and I know this is wrong, is that async doesn't use multithreading, but it does require it, otherwise it's just a synchronous method lying to you.
So here's what might help. If async truly does not require multithreading, the following situation must be producible, I just can't find a way to do it. Can somebody create an example of a method that follows these rules:
Asynchronous.
Actually runs asynchronously.
Doesn't use any multithreading like calling Task.Run() or using a BackgroundWorker etc.
Doesn't call any other Async methods (unless you can also prove that this method follows these rules too).
Doesn't call any methods of the Task class like Task.Delay() (unless you can also prove that this method follows these rules too).
Any help or clarification would be really helpful! I feel like an idiot for not understanding this topic.
The easiest example of an async operation that does not use any kind of threads is waiting for a event to happen.
Create a UI app with your framework of choice and have two buttons, one called PrimeButton and one called RunButton
private TaskCompletionSource<object> _event = new TaskCompletionSource<object>();
//You are only allowed to do async void if you are writing a event handler!
public async void PrimeButton_OnClick(object sender, EventArgs e)
{
//I moved the code in to Example() so the async void would not be a distraction.
await Example();
}
public async Task Example()
{
await _event.Task;
MessageBox.Show("Run Clicked");
}
public async void RunButton_OnClick(object sender, EventArgs e)
{
_event.SetResult(null);
}
The await will wait till you click the 2nd button before it allows the code to continue and show the message box. No extra threads where involved at all here, all work was done using only the UI thread.
All a Task is, is a object that represents "something that will be finished at some point in the future". That something could be waiting for a background thread to complete that was started by a Task.Run or it could be waiting for a function to be called like the .SetResult( on the TaskCompletionSource<T>, or it could be waiting for some kind of disk or network IO to finish and be read in to a buffer by the OS (however internally this is usually implemented via a internal TaskCompletionSource<T> buried inside of the ReadAsync() function, so it is just a repeat of the last example with a wrapper around it)
This question already has answers here:
What's the new C# await feature do? [closed]
(5 answers)
Does await create another thread internally before shifting to the same thread as the caller (for UI application)
(2 answers)
Regarding how Async and Await works c#
(7 answers)
What am I doing wrong with async/await? [closed]
(1 answer)
Closed 5 years ago.
I am still struggling to fully understand async/await approach. Can anyone tell me as in topic does await really does Task.Run behind? Sometimes people doing async metod including await but saw sometimes people do Task.Run without async method. What is the the right way?
No, async await is just made to allow code to run whilst something else is blocking, and it doesn't do Task.Run, or start a new thread.
https://blog.stephencleary.com/2013/11/there-is-no-thread.html is a decent explanation of it.
The async operator simply turns on the use of the await operator in a method. The await operator will work on anything which is awaitable. In .NET, Task and Task<T> are some examples of awaitables.
Task.Run returns Task and Task.Run<T> returns Task<T> and as I said they are both awaitable so you can await on them.
You can even write your own awaitable type if you want: You just have to make sure to satisfy the requirements of what is considered an awaitable. An awaitable needs to provide an implementation for GetAwaiter and that's it. Here is an awaitable example:
public struct SimpleInt32Awaitable
{
public SimpleInt32Awaiter GetAwaiter()
{
return new SimpleInt32Awaiter();
}
}
public struct SimpleInt32Awaiter
{
public bool IsCompleted { get { return true; } }
public void OnCompleted(Action continuation)
{
}
public int GetResult()
{
return 5;
}
}
And now you can do this:
// Within some other class
static async void SimpleWaitAsync()
{
SimpleInt32Awaitable awaitable = new SimpleInt32Awaitable();
int result = await awaitable;
}
does await really does Task.Run behind?
Others have already linked to one of Cleary's many excellent blog posts on C# concurrency, There Is No Thread.
No, it doesn't use Task.Run behind the scenes.
await is useful for more than just Task.Run. It's for running code after something has completed. That something could be a computation task created with Task.Run, but it could also be, say, data-retrieval, such as with ReadLineAsync. Task is the class used to model all of those somethings.
Task.Run is used to queue work to run on the thread-pool. This is appropriate when writing CPU-bound code, but you shouldn't use Task.Run when dealing with IO-bound operations. In that case, your asynchronous code (perhaps using async/await) should make use of asynchronous IO methods such as WriteLineAsync and the aforementioned ReadLineAsync.
It's an anti-pattern to use Task.Run to run blocking code on a worker thread. You never want to do that, even if it does, say, unblock your GUI thread.
Sometimes people doing async metod including await but saw sometimes people do Task.Run without async method. What is the the right way?
You can indeed create a Task using Task.Run and just let it run, without using await or ContinueWith. These are called 'fire and forget' tasks. They're rarely a good idea. Unlike when await is used, any exception thrown by that task will be lost.
This is explained by -- you guessed it -- Stephen Cleary, in this StackOverflow answer.
There are cases where you are restricted from using async and await - this is, generally, why you will sometimes see Task.Run used instead - this allows you to utilize async code in a synchronous method.
An example of where this is necessary is when using MVC with Child Actions - the framework does not support async child actions, so you must call async code using Task.Run.
This question already has answers here:
At the end of an async method, should I return or await?
(2 answers)
Closed 5 years ago.
I see some colleague code where he chooses to not await the database call and just return the Task. E.g.
public Task<UpdateResult> AddActivityAsync(ClaimsPrincipal principal, Activity activity)
{
return _userManager.SaveToDatabaseAsync(principal, activity);
}
as _userManager.SaveToDatabaseAsync is async, I would have implemented this way
public async Task<UpdateResult> AddActivityAsync(ClaimsPrincipal principal,
Activity activity)
{
return await _userManager.SaveToDatabaseAsync(principal, activity);
}
The calling method of this method always await it:
await _profile.AddActivityAsync(..., ...)
Is there any benefit to not make the inner method async and just return the Task, letting the caller await it ? I thought we had to write Async all the way down...
It depends on the situation.
You must await, for example, if the code to be awaited is bound to an object that is in an using context (or gets manually disposed):
using (SomeDisposableType obj = ...)
{
await obj.SomeOperationAsync();
}
If you returned the task without awaiting it, then the method might complain that the object had been disposed before it could have finished its job. (not all disposable objects throw an ObjectDisposedException if you attempt to perform something on them after they get disposed but it is generally a good idea to assume so). Consider the opposite:
using (SomeDisposableType obj = ...)
{
// This returns the Task that represents the async operation,
// and because it returns, the control goes out of the using
// scope, and therefore obj gets disposed.
return obj.SomeOperationAsync();
}
So there are cases when awaiting is necessary. If that is not the case, I can't really think of a reason why you couldn't return the Task itself.
You do not need to await a method which returns a Task<T>, the code will just run asynchronously if you have the async keyword on the method. You colleague has removed that and so is running synchronously deliberately and lets the calling code implement it if they so choose.
It depends at which layer this code is being run. If it is deep it may be better to let the higher code layers choose ansynchronous execution and maintain control there.
You definitely don't need to 'write async all the way down'. The purpose of the async keyword is simply to mark a method as being able to return a Task<T> and be able to use the await keyword. The await keyword is what invokes the framework to execute the Task and provide asynchronous processing.
TL;DR: It's a choice.
I welcome anyone improving or correcting me on this as I am no guru.