Convert TaskCompletionSource to Task.FromResult<TResult>? - c#

I have this simple code which start a method asynchronously. it uses TCS in order to wrap the code with Task.
Task<int> DoWork()
{
var source = new TaskCompletionSource <int>();
Thread.Sleep(220);
source.SetResult(9999999);
return source.Task;
}
void Main()
{
Console.WriteLine(1);
var t1=Task.Factory.StartNew(()=>DoWork());
t1.ContinueWith(_=>Console.WriteLine ("doing something different "));
t1.ContinueWith(_=>Console.WriteLine ("finished , value is ="+_.Result.Result));
Console.WriteLine(2);
Console.ReadLine();
}
output :
1
2
doing somethign different //those last 2 lines can be swapped
finished , value is =9999999
But now , I want to convert it to use Task.FromResult<TResult>.
This is poorly documented , so I wonder , how can I convert my code above to use Task.FroResult instead ?

The easiest way to use FromResult would be to do:
public Task<int> DoWork()
{
return Task.FromResult(99999);
}
But it's an exact functional equivalent of doing:
var tcs = new TaskCompletionSource<int>();
tcs.SetResult(99999);
return tcs.Task;
so it doesn't sleep for 220 ms. For the 'delayed' variant, easiest way would be:
public async Task<int> DoWork()
{
await Task.Delay(220);
return 99999;
}
and this version behaves close enough to the example you provided.

In your code, you return the Task only after the synchronous wait is over, so your code is equivalent to:
Task<int> DoWork()
{
Thread.Sleep(220);
return Task.FromResult(9999999);
}
But if you returned the Task immediately and then blocked some other thread:
Task<int> DoWork()
{
var source = new TaskCompletionSource<int>();
Task.Run(() =>
{
Thread.Sleep(220);
source.SetResult(9999999);
});
return source.Task;
}
(Note: I'm not saying you should do this in real code.)
This code couldn't be simulated by Task.FromResult(), because that always creates an already completed Task.

Related

not understanding of async await concept [duplicate]

This question already has an answer here:
Async Await Running Synchronously
(1 answer)
Closed 2 years ago.
I do not understand when I read the Microsoft documents about async and await working, as it says
Async methods are intended to be non-blocking operations. An await
expression in an async method doesn’t block the current thread while
the awaited task is running. Instead, the expression signs up the rest
of the method as a continuation and returns control to the caller of
the async method.
so consider my code:
public Form1()
{
InitializeComponent();
AsyncTest();
Test(1);
}
private async void AsyncTest()
{
HttpClient client = new HttpClient();
var ss = TT(2);
var s = await ss;
for (int i = 0; i < 10; i++)
{
//loop
}
}
private async Task<int> TT(int i)
{
while (true)
{
if (i > 1000000000)
break;
i++;
}
return i;
}
}
when ever I call AsyncTest(), it just waits behind TT method as it specified with await key, but what does it mean it return control to the main caller??
it is not been returned to the form1, if TT is an infinite loop it just remains forever.
thanks
It seems to me you are a newbee to async-await. You violate several rules about how to use async-await.
To make a function async do the following:
Declare the function async
Return Task<TResult> instead of TResult; return Task instead of void
ONLY EXCEPTION: event handlers return void instead of Task
there should be one await inside your async function. Your compiler will warn you if you omit this.
Make sure that all async functions that you call are awaited for before you return
Guideline: let async be a suffix to your async functions. This allows you to create a sync and an async function that do the same: void MyTest() and Task MyTestAsync()
Following these rules, you can't call an async function from within a constructor. As you are using Winforms your code could be like this:
public Form1()
{
InitializeComponent();
}
public async void OnButton1_Clicked(object sender, ...)
{ // because this is an event handler the return value is void
// Start the first test and await until ready
await TestAsync();
// Start the second test and await until ready:
int i = await TestAsync(1);
}
If you call an async function you know that somewhere inside this function is an await. If you have meaningful things to do while the inner function is awaiting, do not await yet. Do your useful things after the call and await the returned Task as soon as you need the result:
public async void OnButton2_Clicked(object sender, ...)
{
// Start a test, but don't await yet
var task1 = TestAsync(1);
// if here, function TestAsync is awaiting somewhere
// it is not finished yet, so you can't use the result of it
// But you can do Something else:
DoSomethingElse();
// if here you really need the result of TestAsync, await for it
int i = await task1;
// if here you know that TestAsync is finished, i has the proper return value
}
You don't have to start and await the tasks one by one, you can start several tasks and await for them as soon as you need the results:
public async void OnButton3_Clicked(object sender, ...)
{
// start several tasks. Don't await yet:
var task1 = TestAsync(1);
var task2 = TestAsync(2);
var task3 = TestAsync(3);
DoSomethingElse();
// if here I need the results of all three tasks:
var myTasks = new Task[] {task1, task2, task3};
await Task.WhenAll(myTasks);
}
An article that really helped me understanding async-await is this interview with Eric Lippert, where he compares async-await with a cook making breakfast. If a cook has to wait for the water to boil, he doesn't wait idly, but looks around to see if he can do other things. Search somewhere in the middle for async-await.
Another article that helped me following the guidelines of async-await is Async and Await by the ever so helpful Stephen Cleary

c#-WPF: Cannot convert async lambda expression to delegate type 'Func<int>'

Im trying to understand how Lambda expression work with async methods.
I have a function
private int Server_Get_Int(){
Task<int> task = Task.Factory.StartNew<int>( async () => {
FirebaseClient c = Server_Connect();
FirebaseResponse response = await c.GetAsync("todos/set");
return response.ResultAs<int>(); //The response will contain the data being retreived
} );
task.Wait();
int result = task.Result;
Console.WriteLine(result);
return result;
}
I want my async code to run in the lambda expression and get back the result from the server.
But i get back the error:
error CS4010: Cannot convert async lambda expression to delegate type 'Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<int>'.
It says i can only return a void, task or task<> and to my understanding im returning
task<int>
Is this a problem with what im returning or is this because of async lambda?
Thanks
Edit:
response.ResultAs<int>()
Returns an Int but being inside a Task function it should be returned as a Task
Your whole method is suboptimal. You could rewrite your code to be much simpler. A few comments on your existing code first, however.
You're using Task.Factory.StartNew(), which is dangerous. In
most cases you should simply use Task.Run()
You're using Task.Wait() and Task.Result, which is also suboptimal, not to mention, that Task.Result includes Task.Wait() when accessing it. But I guess, that you want to test the lambda, so it's ok here.
The ResultAs<T>() method converts the response into an int (in your case). The method itself is defined as public virtual T ResultAs<T>(). It needn't return a Task<int>, because your lambda is asynchronous. If you'd remove the async from the lambda you'd have to return a Task<int>, but you can'T do that by simply changing the ResultAs<T> to ResultAs<Task<int>>, you'd have to use a TaskCompletionSource.
Based on the above that we can rewrite your method to this:
private int Server_Get_Int(){
var task = Task.Run(async () => {
var c = Server_Connect();
return (await c.GetAsync("todos/set")).ResultAs<int>();
});
int result = task.Result;
Console.WriteLine(result);
return result;
}
A more concise approach could look like this:
private async Task<int> Server_Get_Int_Async(){
return await Task.Run(async () => {
var c = Server_Connect();
return (await c.GetAsync("todos/set")).ResultAs<int>();
});
}
This creates a new task via Task.Run() and returns that to be completed later.
Based on the comments here are tow ways how you'd call the Server_Get_Int_Asnyc() method. I used explicit types so you can follow my comment, but in almost any case it's better to use var, because the compiler than can choose the best type for the job.
public async Task Foo()
{
// This is the fetch task that's going to be completed sometime in the future. You should almost in any case use configure await on your tasks. For reasons see below.
Task<int> intTask = Server_Get_Int_Async().ConfigureAwait(false);
// Do something other with the task object
// Finally await it and print
int result = await intTask;
Console.WriteLine(result);
}
// Do this if you just need the result and nothing else.
public async Task Bar()
{
int result = await Server_Get_Int_Async().ConfigureAwait(false);
Console.WriteLine(result);
}
In the end it seems, you're pretty new to Task based programming with async/await. I recommend you read the (excellent) introduction article written by Stephen Cleary and go on from there.
The beauty of async/await is, that it propagates naturally through your code and you can write asynchronous code almost like you'd write synchronous code.
Also, placing another article here on why you shouldn't use Wait() or Result to simply get the return value of the async method, since it's going to be noticed much better:
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Test code (console app). This correctly shows "Result: 10".
static void Main(string[] args)
{
Func<Task<int>> func = async () => { await Task.Delay(1000); return 10; };
var task = Task.Factory.StartNew(func);
task.Wait();
int result = task.Unwrap().Result;
WriteLine($"Result: {result}");
ReadKey(true);
}

C# Async method call all the way to Main

Can someone clarify this example, which of course, is not working:
class Program
{
static void Main(string[] args)//main cant' be async
{
int res = test();//I must put await here
Console.WriteLine("END");
}
public async static Task<int> test()
{ //why can't I make it just: public int test()??
int a1, a2, a3, a4;
a1 = await GetNumber1();
a2 = await GetNumber2();
a3 = await GetNumber3();
a4 = a1 + a2 + a3;
return a4;
}
public static async Task<int> GetNumber1()
{
await Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("GetNumber1");
System.Threading.Thread.Sleep(100);
}
});
return 1;
}
I am trying to "collect" values from GenNumberX methods by using "await". I would like to make method "test" not async somehow. I dont understand why test has to be async when I am using await to get a value. This example makes me to write async on every method where I use async, and when I drill up to Main, I cannot make it async?
How to write real-world example:
public bool ReserveAHolliday()
{
bool hotelOK = await ReserveAHotel();//HTTP async request
bool flightOK = await ReserveFlight();////HTTP async request
bool result = hotelOK && flightOK;
return result;
}
How to make method ReserveAHolliday synchronous?
Am I missing something or don't understand the use of async-await mechanism?
below is a full example. you can run the ReserverAHoliday both Synchronously (bool r = ReserveAHolliday().Result;) and Asynchronously (just call ReserveAHolliday();) from MAIN (depends which line you comment). and you can see the effect ("END" gets printed before / after the reservation is complete).
I prefer the await Task.WhenAll() methods, which is more readable.
also note that it's preferred to use await Task.Delay(100) instead of Thread.sleep inside GetNumber1.
class Program
{
static void Main(string[] args)//main cant' be async
{
//int res = test().Result;//I must put await here
bool r = ReserveAHolliday().Result; //this will run Synchronously.
//ReserveAHolliday(); //this option will run aync : you will see "END" printed before the reservation is complete.
Console.WriteLine("END");
Console.ReadLine();
}
public async static Task<int> test()
{ //why can't I make it just: public int test()??
//becuase you cannot use await in synchronous methods.
int a1, a2, a3, a4;
a1 = await GetNumber1();
a2 = await GetNumber1();
a3 = await GetNumber1();
a4 = a1 + a2 + a3;
return a4;
}
public static async Task<int> GetNumber1()
{
//await Task.Run(() =>
// {
for (int i = 0; i < 10; i++)
{
Console.WriteLine("GetNumber1");
await Task.Delay(100); // from what I read using Task.Delay is preferred to using System.Threading.Thread.Sleep(100);
}
// });
return 1;
}
public async static Task<bool> ReserveAHolliday()
{
//bool hotelOK = await ReserveAHotel();//HTTP async request
//bool flightOK = await ReserveAHotel();////HTTP async request
var t1 = ReserveAHotel("FirstHotel");
var t2 = ReserveAHotel("SecondHotel");
await Task.WhenAll(t1, t2);
bool result = t1.Result && t1.Result;// hotelOK && flightOK;
return result;
}
public static async Task<bool> ReserveAHotel(string name)
{
Console.WriteLine("Reserve A Hotel started for "+ name);
await Task.Delay(3000);
if (name == "FirstHotel")
await Task.Delay(500); //delaying first hotel on purpose.
Console.WriteLine("Reserve A Hotel done for " + name);
return true;
}
}
First of all never use Result it has a bad implementation and you
will end up having deadlocks. Instead use GetAwaiter().GetResult()
If you are using C# 7.0 or below then it's safe to use this pattern:
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
private static async Task MainAsync(string[] args)
{
await MyMethod();
await MyOtherMethod();
Console.WriteLine("Done!");
}
private static async Task MyMethod()
{
// do something
await Task.CompletedTask;
}
private static async Task MyOtherMethod()
{
// do something
await Task.CompletedTask;
}
If you are using C# 7.1+ then you can change the main method to be an async one like this:
static async Task Main(string[] args)
{
await MyMethod();
await MyOtherMethod();
Console.WriteLine("Done!");
}
private static async Task MyMethod()
{
// do something
await Task.CompletedTask;
}
private static async Task MyOtherMethod()
{
// do something
await Task.CompletedTask;
}
In .Net core project you can change to C# 7.1 or higher by using this tag:
<LangVersion>7.1</LangVersion>
or
<LangVersion>latest</LangVersion>
The project file will look like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
</Project>
Thank you FrankerZ for the right answer!
So my litle example should look something like this:
class Program
{
static void Main(string[] args)
{
var task = test();
task.Wait(); //this stops async behaviour
int result = task.Result;// get return value form method "test"
Console.WriteLine("RESULT IS = " + result);
}
public async static Task<int> test()
{
int a1, a2, a3, a4;
//run all tasks
//all tasks are doing their job "at the same time"
var taskA1 = GetNumber1();
var taskA2 = GetNumber2();
var taskA3 = GetNumber3();
//wait for task results
//here I am collecting results from all tasks
a1 = await taskA1;
a2 = await taskA2;
a3 = await taskA3;
//get value from all task results
a4 = a1 + a2 + a3;
return a4;
}
public static async Task<int> GetNumber1()
{
await Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("GetNumber1");
System.Threading.Thread.Sleep(100);
}
});
return 1;
}
//other methods are ommited because they are the same like GetNumber1
}
In order to use the await keyword inside a method, it has to be async. This was a design decision to make it easier to be backwards compatible.
Main cannot be async as it is the starting point of the program, so you typically need to block somehow to keep the program running. You can do that by blocking on a Task or even by calling Console.ReadLine.
Tasks usually execute on a background thread and background threads do not keep your program running if all foreground threads stop.
I've got an introductory blog post on async-await here
Your async needs to start somewhere, and since your program has a starting point, it's a synchronous method at this point. Most async's start at what we like to call async void's, which are basically fire and forget methods. It starts a task, and doesn't care what it returns. If you need to wait for something in a synchronous method, you can use the .Wait() method on a task, or use .Result to get the result of the task.
For your real world example, if you want to run both tasks at the same time, you would need to do something like this:
public async Task<bool> ReserveAHoliday()
{
//Initialize and start this task
Task<bool> hotelTask = ReserveAHotel();//HTTP async request
//Initialize and start this task
Task<bool> flightTask = ReserveFlight();////HTTP async request
//Await until hotel task is done, and get the bool
bool hotelOK = await hotelTask;
//Await until flight task is done (This might have already finished while the hotel was grabbing, and get the bool
bool flightOK = await flightTask;
bool result = hotelOK && flightOK;
//Return the final result
return result;
}
I highly recommend watching this video. It gives a nice introduction to how Async works, and can jump start you in the wonderful world of Async.
The method ReserveAHolliday cannot be made synchronous if you use the await keyword inside of it.
What could be possible is to simply block till both async methods return their value. I don't recommend it though because it could lead to deadlocks or other unexpected errors.
If you don't have a synchronization context (eg. console application) you can simply write
bool hotelOK = ReserveAHotel().Result;
But I reckon you ultimately want to create a GUI. That is where blocking falls apart. Because UI application (Forms and WPF) do have a context and waiting for asynchronous methods cause deadlocks. Read more here
There are workarounds for this problem, but they are highly dependent on the design of your application.
Edit:
If your library code needs Synchronization Context then blocking will most certainly cause a deadlock.
If you don't need it, it's possible to use ConfigureAwait(false) in your library code and get away with blocking.
What I recommend is: async/await all the way or no async/await at all. There are other possibilities to make your code asynchronous, eg: event based, but like everything in life has pros and cons.
Please read this blog from Stephen Cleary. He explains why blocking async code will deadlock and how you can avoid it.

Is it OK to do some async/await inside some .NET Parallel.ForEach() code?

Given the following code, is it OK to do async/await inside a Parallel.ForEach ?
eg.
Parallel.ForEach(names, name =>
{
// Do some stuff...
var foo = await GetStuffFrom3rdPartyAsync(name);
// Do some more stuff, with the foo.
});
or is there some gotcha's that I need to be made aware of?
EDIT: No idea if this compiles, btw. Just Pseduo-code .. thinking out loud.
No, It doesn't make sense to combine async with Paralell.Foreach.
Consider the following example:
private void DoSomething()
{
var names = Enumerable.Range(0,10).Select(x=> "Somename" + x);
Parallel.ForEach(names, async(name) =>
{
await Task.Delay(1000);
Console.WriteLine("Name {0} completed",name);
});
Console.WriteLine("Parallel ForEach completed");
}
What output you will expect?
Name Somename3 completed
Name Somename8 completed
Name Somename4 completed
...
Parallel ForEach completed
That's not what will happen. It will output :
Parallel ForEach completed
Name Somename3 completed
Name Somename8 completed
Name Somename4 completed
...
Why? Because when ForEach hits first await the method actually returns, Parallel.ForEach doesn't know it is asynchronous and it ran to completion!. Code after await runs as continuation on another thread not "Paralell processing thread"
Stephen toub addressed this here
From the name, I'm assuming that GetStuffFrom3rdPartyAsync is I/O-bound. The Parallel class is specifically for CPU-bound code.
In the asynchronous world, you can start multiple tasks and then (asynchronously) wait for them all to complete using Task.WhenAll. Since you're starting with a sequence, it's probably easiest to project each element to an asynchronous operation, and then await all of those operations:
await Task.WhenAll(names.Select(async name =>
{
// Do some stuff...
var foo = await GetStuffFrom3rdPartyAsync(name);
// Do some more stuff, with the foo.
}));
A close alternative might be this:
static void ForEach<T>(IEnumerable<T> data, Func<T, Task> func)
{
var tasks = data.Select(item =>
Task.Run(() => func(item)));
Task.WaitAll(tasks.ToArray());
}
// ...
ForEach(names, name => GetStuffFrom3rdPartyAsync(name));
Ideally, you shouldn't be using a blocking call like Task.WaitAll, if you can make the whole chain of methods calls async, "all the way down" on the current call stack:
var tasks = data.Select(item =>
Task.Run(() => func(item)));
await Task.WhenAll(tasks.ToArray());
Furthermore, if you don't do any CPU-bound work inside GetStuffFrom3rdPartyAsync, Task.Run may be redundant:
var tasks = data.Select(item => func(item));
As pointed out by #Sriram Sakthivel there are some problems with using Parallel.ForEach with asynchronous lambdas. Steven Toub's ForEachASync can do the equivalent. He talks about it here, but here is the code:
public static class Extensions
{
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select Task.Run(async delegate {
using (partition) while (partition.MoveNext()) await body(partition.Current);
}));
}
}
It uses the Partitioner class to create a load balancing partitioner(doco), and allows you to specify how many threads you want to run with the dop parameter. to see the difference between it and Parallel.ForEach. Try the following code.
class Program
{
public static async Task GetStuffParallelForEach()
{
var data = Enumerable.Range(1, 10);
Parallel.ForEach(data, async i =>
{
await Task.Delay(1000 * i);
Console.WriteLine(i);
});
}
public static async Task GetStuffForEachAsync()
{
var data = Enumerable.Range(1, 10);
await data.ForEachAsync(5, async i =>
{
await Task.Delay(1000 * i);
Console.WriteLine(i);
});
}
static void Main(string[] args)
{
//GetStuffParallelForEach().Wait(); // Finished printed before work is complete
GetStuffForEachAsync().Wait(); // Finished printed after all work is done
Console.WriteLine("Finished");
Console.ReadLine();
}
if you run GetStuffForEachAsync the program waits for all work to finish. If you run GetStuffParallelForEach, the line Finished will be printed before the work is finished.

Task.Factory.StartNew with parameters and return values

Trying to call a method that requires parameters in order to get a result and pass the result to proceed. But I'm new to the Task area and can't seem to figure out the correct syntax. Any help would be appreciated.
Task.Factory.StartNew(() =>
CheckConflict(startDate, endDate, actID, repeatRule,whichTime))
.ContinueWith(
GetConflictDelegate(result),
TaskScheduler.FromCurrentSynchronizationContext);
Assuming you want to continue with the result of CheckConflict(), ContinueWith takes a Task<T> as an argument. Task<T> has a property Result, which will be the result from the method invocation.
See my code snippet below, for an example.
new TaskFactory()
.StartNew(() =>
{
return 1;
})
.ContinueWith(x =>
{
//Prints out System.Threading.Tasks.Task`1[System.Int32]
Console.WriteLine(x);
//Prints out 1
Console.WriteLine(x.Result);
});
I recommend you use async/await:
var result = await Task.Run(
() => CheckConflict(startDate, endDate, actID, repeatRule, whichTime);
GetConflictDelegate(result);
Task.Factory.StartNew<TResult>(new Func<TResult>(() =>
{
return 1;
}).ContinueWith<TResult>(new Action((result) =>
{
Console.Writeline(result.Result); // output: 1
});
Try this one
You need the Task<TResult> class (see MSDN - TaskFactory.StartNew-Methode (Func, Object). <TResult> is the return type of your invoked method.
Because you starting a new thread you have to wait until thread is finished without blocking the main thread or leading the messagepump to stop. This is where you can use async and await.
Assuming a method Calculate() which is taking two parameters of type double and returning a result of double and a second method called Validate() which validates the result. The solution could look like this:
private async Task CalculateAsync()
{
// Our parameter object
CustomArgsObject customParameterObject = new CustomArgsObject()
{
Value1 = 500,
Value2 = 300
};
Task<double> returnTaskObject = await Task<double>.Factory.StartNew(
(paramsHoldingValues) => Calculate(paramsHoldingValues as CustomArgsObject),
customParameterObject);
// Because of await the following lines will only be executed
// after the task is completed while the caller thread still has 'focus'
double result = returnTaskObject.Result;
Validate(result);
}
private double Calculate(CustomArgsObject values)
{
return values.Value1 + values.Value2;
}
private bool Validate(double value)
{
return (value < 1000);
}
The await returns focus back to the the caller thread (thread who called CalculateAsync() ) to prevent locking while the task is running. At the same time await forces the CalculateAsync() to be processed until the line where the task is started and then waits until the task is completed. The the rest of the CalculateAsync() will then be processed.
Without await the whole method would be processed - before the task is finished or simultaneous to the running task.
The Task<TResult> class (where <TResult> is the placeholder for your return type) has a property Result that holds the return value of type <TResult>.
This works:
Task.Factory.StartNew(()=>
{
return CheckConflict(startDate, endDate, actID, repeatRule,whichTime);
}).ContinueWith(x=>
{
GetConflictDelegate(whichTime);
},TaskScheduler.FromCurrentSynchronizationContext());

Categories