Should I use taskThatReturns.Wait() in code below or I can omit it since according to my understanding taskThatReturns.Result will do wait anyway.
Task<string> taskThatReturns = new Task<string>(MethodThatReturns);
taskThatReturns.Start();
taskThatReturns.Wait();
Console.WriteLine(taskThatReturns.Result);
The call of Wait() before accessing Result is unnecessary.
Examination of the reference code of Task and Task<TResult> shows that both the void Wait() method and the getter of the Result property eventually make their way into the method that does the actual waiting:
internal bool InternalWait(int millisecondsTimeout, CancellationToken cancellationToken)
Both code paths send identical parameter values to InternalWait - infinite wait and default cancellation token.
If you call Wait before accessing Result, the code path inside the getter leading to InternalWait would be skipped, because the task is known to be completed. However, the net result would remain the same in both cases.
Note: This answer intentionally ignores opportunities to optimize your code fragment.
async void DoTask() {
string task = await returnString();
Console.WriteLine(task);
}
Task<string> returnString() {
// you code here
}
You can use async method to await Task execution
To answer the actual question. You either need to wait to get the results, or you need to do as Panagiotis Kanavos suggested, and await a task. You're overcomplicating threading, a common issue with all the bad examples out there.
If you still want to use Task better approach is:
var result = taskThatReturns.GetAwaiter().GetResult();
Related
Currently I am learning the bloc library for Flutter and I stumbled across this Function, I may be too unfamiliar with the exact implementation of Futures in Dart.
Here I am required to use the async keyword, since I am using await.
I would like to return an Item but am not allowed to, since I used the async keyword and have to return a Future.
Is the Item being wrapped up in a Future "artificially", because I've awaited already, so what is the point of the return type being a Future?
Does this result in a small overhead?
Future<Item> getItem(String id) async{
Item item = await _itemApiClient.getItemById(id);
return item;
}
With this implementation I am able to use "await" simply one time; when awaiting the getItem() function.
Future<Item> getItem(String id) {
Future<Item> item = _itemApiClient.getItemById(id);
return item;
}
Your function is perfectly fine.
I'd even do:
Future<Item> item(String id) => _itemApiClient.getItemById(id);
Yes, there is an overhead in having an async function.
The async function always creates its own Future for its result, and there is an overhead moving the value from the getItemById-returned future to the future returned by getItem.
The overhead may or may not affect timing, depending on how the underlying futures are created. (It's possible that the value is propagated immediately when the first future completes, but there are no promises.) There is always a memory overhead.
I have a confusion in understanding Dart's async/await functionality. Most tutorials use the following example:
Future<String> createOrderMessage() async {
var order = await fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
// Imagine that this function is
// more complex and slow.
Future.delayed(
const Duration(seconds: 2),
() => 'Large Latte',
);
Future<void> main() async {
print('Fetching user order...');
print(await createOrderMessage());
}
I understand that the fetchUserOrder function returns a Future. Anyone who calls this function will immediately get a Future object as a result but this Future object may not have the real result value at that time. It will be filled up in "future".
Now, the createOrderMessage function calls: await fetchUserOrder(); This means, the control will wait till fetchUserOrder() returns a completed/non-empty Future. Am I right here? Is this what await does?
If that is correct, it means, the createOrderMessage function is essentially synchronous now because it won't return until the Future returned by fetchUserOrder is filled. Thus, the order variable in this function is initialized with a completed Future. Then why does this function need the "async" keyword in its function declaration? What does it signify?
Second confusion is if Dart is single threaded, when and how exactly is an async function executed? If I invoke multiple method calls that return Futures like this without await:
...
Future<A> fa = getA();
Future<B> fb = getB();
Future<C> fa = getC();
...
Will the functions getA, getB, and getC be executed sequentially in the background or they will be executed "in parallel" somehow?
Now, the createOrderMessage function calls: await fetchUserOrder(); This means, the control will wait till fetchUserOrder() returns a completed/non-empty Future. Am I right here? Is this what await does?
Yes. the await keyword means you get the completed T instead of Future<T> in return. So:
var a = fetchUserOrder(); // Type of a: Future<String>
var b = await fetchUserOrder(); // Type of b: String
When you use await, you tell the code to await the completion of the process and get the actual result. But without await, the stream is in the future and is in process until you await it somewhere else.
why does this function need the "async" keyword in its function declaration?
It's a rule to specify long-running functions. So when a function awaits for a long running process to complete, the function itself is also a long-running process. Why? Because it's waiting for another one to complete.
Therefore, you need to specify async for that as well. When another function is calling this one, it also knows this one might be long-running.
In short, every awaitable function needs to be in an async function.
Second confusion is if Dart is single threaded, when and how exactly is an async function executed?
You're mixing the concept of parallelism with asynchronous. An async process does not have to be done in multi thread.
Async processes can be one one at time, but in a different order in compare to synchronous code.
Take a look at this article which explains asynchronous in a single thread.
Now, the createOrderMessage function calls: await fetchUserOrder(); This means, the control will wait till fetchUserOrder() returns a completed/non-empty Future. Am I right here? Is this what await does?
If that is correct, it means, the createOrderMessage function is essentially synchronous now because it won't return until the Future returned by fetchUserOrder is filled. Thus, the order variable in this function is initialized with a completed Future.
await allows asynchronous functions to have the appearance of synchronous functions by allowing asynchronous code to be structured very similarly to synchronous code. In your example, it's syntactic sugar for registering a Future.then() callback and immediately returning:
Future<String> createOrderMessage() {
var future = fetchUserOrder().then((order) {
return 'Your order is: $order';
});
return future;
}
await defers execution of the rest of that function; it does not wait and block execution of your entire thread. Your program will continue running its event loop, possibly allowing other asynchronous operations to make progress.
Will the functions getA, getB, and getC be executed sequentially in the background or they will be executed "in parallel" somehow?
As I mentioned in comments, it depends on how getA, getB, and getC are implemented. They could run in parallel, such as if they run in separate Dart isolates or in separate threads in the Dart VM/runtime.
I am trying out the Future with async await for asynchronous programming.
The code i tested is a simple Future.
//order a new coffee perhaps!
Future<String> order(String newOrder){
final String Function() func = ()=> "${newOrder} is requested!";
final _order = Future.delayed(Duration(seconds: 5),func);
return _order;
}
When i run this code like a promise.
order("promised order")
.then((result) => print(result))
.catchError((err){
print(err.error);
});
This behaves like a asynchronous non-blocking code
However the same code when i run it with async/await behaves like a synchronous code and blocks all the other code, it waits 5 secs to run the next line.
void main(List<String> arguments) async {
final _myOrder = await order('Lattee mocha');
print(_myOrder);
//...all the other code waits for
}
So i thought async/await is same as futures, where non-blocking..
How come it blocks the other code execution ?
The whole point of the async/await pattern is to wait (hence await) until the Future completes and only then continue with this code execution.
Think of it as a way to not have endless .then() chains and much simplified error handling.
If you want to not wait, then you just leave out the await keyword. Obviously, if you don't (a)wait, you don't get the result.
You can still use classic .then() chains when it suits your purpose better in your program.
What people talk about when they say "non blocking" they mean that when the compiler sees the await keyword, it knows to keep the rest of the program, the event loops, animations etc running and not block the complete program.
the code shown below is executed inside an asp.net mvc application
public async Task<string> GetCustomers1(){
return await getcustomer1Async();
}
public async Task<string> GetCustomers2(){
return await getcustomer2Async();
}
public async Task<JsonResult> Index(){
var result1 =Task.Run(()=>GetCustomers1());
var result2 =Task.Run(()=>GetCustomers2());
Task.WaitAll(result1,result2);
}
I am clear that task run will create two threads to execute methods GetCustomers1, GetCustomers2.
- my question is when the method GetCustomers1 and GetCustomers2 reach the line that has the word await, should the incomplete task be returned, where should the incomplete task be returned? Does the thread return to the thread pool?
-Task.WaitAll would you have the main thread busy until the other tasks finish running?
I know you shouldn't use tak.run if the method is asynchronous. But I want to know how the code works internally in such a scenario.
I am clear that task run will create two threads to execute methods GetCustomers1, GetCustomers2.
Task.Run doesn't create threads. It queues work to the thread pool.
my question is when the method GetCustomers1 and GetCustomers2 reach the line that has the word await, should the incomplete task be returned, where should the incomplete task be returned? Does the thread return to the thread pool?
Yes, the thread is returned to the thread pool. When the await is ready to resume execution, the "continuation" of that method is queued to the thread pool. Note that continuations may or may not run on the same thread; they can run on any thread pool thread.
Task.WaitAll would you have the main thread busy until the other tasks finish running?
Yes, that is what Task.WaitAll will do. It also blocks on asynchronous code, which is not a good idea. It's better to go async all the way.
I know you shouldn't use tak.run if the method is asynchronous.
Using Task.Run for asynchronous code is fine. But in the general case, you shouldn't use Task.Run on ASP.NET because it queues work to the thread pool instead of letting ASP.NET have full control of the thread pool. Instead, call the asynchronous code directly and use asynchronous code (Task.WhenAll) instead of blocking code (Task.WaitAll):
public async Task<string> GetCustomers1() {
return await getcustomer1Async();
}
public async Task<string> GetCustomers2(){
return await getcustomer2Async();
}
public async Task<JsonResult> Index(){
var result1 = GetCustomers1();
var result2 = GetCustomers2();
await Task.WhenAll(result1, result2);
}
Yes, at the await line the methods GetCustomers1 and GetCustomers2 will immediately return an incomplete task, assuming that the tasks returned from getcustomer1Async() and getcustomers2Async() are incomplete. The await keyword allows you to write code below the await line, that will run after the awaited task is completed. In your case there is no code below the await line, so you could just as well return directly the tasks without awaiting them:
public Task<string> GetCustomers1()
{
return getcustomer1Async();
}
Notice that not only the await keyword is gone, but the async as well.
As for the Index method, it should give you a compile-time warning for not having an await inside a method marked with the async keyword. You should probably modify it to something like this:
public async Task<JsonResult> Index()
{
var task1 = Task.Run(() => GetCustomers1());
var task2 = Task.Run(() => GetCustomers2());
string[] results = await Task.WhenAll(task1, task2);
//...use the results to create a JsonResult and return it
}
Finally keep in mind that it's common practice to add the suffix Async to the methods that return a Task. So the method GetCustomers1 should be renamed GetCustomers1Async, the Index should be renamed IndexAsync etc. You can read the relevant guidelines here.
I want to execute same future function with different values. The order is not important. But I want to execute some functions after the above future function. My idea is
addrMapList.forEach((addrMap){ //length is 3
exeQuery(sql).then((result){
print(result);
});
});
print('All finished');
// other actions
Future exeQuery(String sql){
var c=new Completer();
Random rnd=new Random();
c.complete(rnd.nextInt(100));
return c.future;
}
But the result is
All finished
72
90
74
But I need a result like
72
90
74
All finished
How can this implement in dart.. Please help.
Here is modified version of your sample to work as you expected it to.
First of all, you should understand how asynchronous code works, and why it was not in your case:
When you write constructions like <some future>.then( (){...} ); you are not immediately running code defined inside .then( ). You just defining a callback, to be called later. So, in your code, you're defined 3 callbacks, and then, immediately, printed "All finished", at the time when no of your futures even started to work. At this moment they are just sitting in dart's event loop and waiting for a chance to be executed. And they will get that chance only when you finish execution of current code, and not a moment earlier, because Isolate is run as a single thread.
I used Future.wait() to wait for multiple futures because you said order is not important. This is more efficient then waiting Futures one by one. But if order is important, you have to use Future.forEach(), it will not start execution of second Future until first one is completed.
One more thing in your code is that your function returning a Future is actually synchronous, because it always returns already completed Future. This is also changed in dartpad sample above to better visualize how asynchronous code works.
forEach can't be used this way. Use await for instead (the enclosing function needs to be async)
Future someFunc() async {
await for (var addrMap in addrMapList) {
var result = await exeQuery(sql);
print(result);
}
// other action
}