Async/await: Making method async - c#

I'm trying to do a simple example but I'm not even getting the basics. What's wrong with this code? Imagine Calculate() takes a few seconds.
static void Main(string[] args)
{
int result = await Calculate();
Console.WriteLine(result);
Console.ReadLine();
}
static async Task<int> Calculate()
{
return 1;
}

Simply change your main to:
static void Main(string[] args)
{
int result = Calculate().Result;
Console.WriteLine(result);
Console.ReadLine();
}
As soon as you use the await keyword, the surrounding method must be marked as async which - as others metnioned - is not possible for Main.
Since async methods like Calculate still return good old Task objects, feel free to use the "old" way of dealing with them: using Result to wait for results. Of course this is a blocking operation - but no reason to be non-blocking inside Main, right? ;)

You can do this:
static void Main()
{
WrapMain();
}
static async void WrapMain()
{
int result = await Calculate();
Console.WriteLine(result);
Console.ReadLine();
}
static async Task<int> Calculate()
{
return await Task.Run(() =>
{
return 1;
});
}

Related

Can't await a task after the fact

How can I fix this Task/Await code? I'm basically calling a method that returns a Task and Awaiting it later. First off, it says that Awaited task returns no value which it does (to me anyway). Then it says it can't convert void to int. How come? Thanks in advance.
class Program
{
static async void Main(string[] args)
{
var tsk = First();
int mynumb = await tsk;
return;
}
static async Task<int> First()
{
return 2;
}
}
The variable type is incorrect.
Change it to this:
Task<int> tsk = First();
or just use the var keyword
var tsk = First();
To remove the warning you need to make the First() method return a Task<int> like the following
static Task<int> First()
{
return Task.FromResult(2);
}
From the code above, it does seem that none of this needs to be asynchronous, so if this is the case you are probably wasting your time here.

What is the best way to make a time measuring wrapper class for functions?

I want to start measuring the time it took for a function to run in my program in multiple locations.
Dealing with the StopWatch seemed a bit messy in the code so i decided to wrap it.
These are the things I need:
the function will receive an async function that may or may not have a return value
i need to get out of the function two things: the return value if it exists and the time in seconds it took for it to run
I want to find a readable and sustainable solution since it will be used in multiple projects.
this is what i did so far:
public class TimeMeasurer
{
private readonly Stopwatch _stopWatch;
public TimeMeasurer()
{
_stopWatch = new Stopwatch();
}
public async Task<Tuple<double, TReturn>> Start<TReturn>(Func<Task<TReturn>> function)
{
try
{
_stopWatch.Start();
var val = await function();
var took = _stopWatch.Elapsed.TotalSeconds;
return Tuple.Create(took, val);
}
finally
{
_stopWatch.Stop();
_stopWatch.Reset();
}
}
public async Task<double> Start(Func<Task> function)
{
try
{
_stopWatch.Start();
await function();
var took = _stopWatch.Elapsed.TotalSeconds;
return took;
}
finally
{
_stopWatch.Stop();
_stopWatch.Reset();
}
}
}
if there isnt a better solution..
Is there a way to merge between the two functions? (one to include a return value and the second to get void functions)
Is there a way to return something clearer than tuple? I find it kind of messy to deal with
edit: calling the class i made also doesnt look good..
var tuple = await _timeMeasurer.Start(async () => await function(param1, param2));
EDIT: I decided to give this idea up. Its too messy. In the end im using StopWatch
For your first point, there is not much more you could do that could combine the functions, there is just not much logic to combine.
For your second point I would make two custom classes to hold the result. You could get fancy and do some inheritance too and return the entire task object instead of just the result in case someone wanted to look at some of the properties of the returned task.
Lastly there is no reason your function should be a instance, the entire class could be made static.
Here is a example that has the changes I suggested.
public class TimeMeasurerResult
{
protected readonly Task _task;
private readonly TimeSpan _duration;
public TimeMeasurerResult(Task task, TimeSpan duration)
{
_task = task;
_duration = duration;
}
public Task Task {get { return _task;}}
public TimeSpan Duration {get {return _duration;}}
}
public class TimeMeasurerResult<T> : TimeMeasurerResult
{
public TimeMeasurerResult(Task<T> task, TimeSpan duration)
:base(task, duration)
{
}
public T Result {get { return ((Task<T>)_task).Result;}}
}
public static class TimeMeasurer
{
public static async Task<TimeMeasurerResult<TReturn>> Start<TReturn>(Func<Task<TReturn>> function)
{
var stopWatch = Stopwatch.StartNew();
var task = function();
await task;
var took = stopWatch.Elapsed;
return new TimeMeasurerResult<TReturn>(task, took);
}
public static async Task<TimeMeasurerResult> Start(Func<Task> function)
{
var stopWatch = Stopwatch.StartNew();
var task = function();
await task;
var took = stopWatch.Elapsed;
return new TimeMeasurerResult(task, took);
}
}
Here is a example of using it, note that I only needed to do var results = await TimeMeasurer.Start(() => Function(a,b)); not var results = await TimeMeasurer.Start(async () => await Function(a,b));
public class Program
{
public static void Main()
{
AsyncMain().Wait();
}
public static async Task AsyncMain()
{
int a = 500;
int b = 10;
var results = await TimeMeasurer.Start(() => Function(a,b));
Console.WriteLine("Waited: {0}", results.Duration.TotalSeconds);
Console.WriteLine("Result: {0}", results.Result);
}
public static async Task<int> Function(int a, int b)
{
var total = a + b;
await Task.Delay(total);
return total;
}
}

How to write extension method which will make invocation list members in multicast C# delegate run sequentially?

I have an async delegate which I await in the async method:
async Task M1()
{
Debug.WriteLine("M1.A");
await Task.Delay(10);
Debug.WriteLine("M1.B");
}
async Task M2()
{
Debug.WriteLine("M2.A");
await Task.Delay(1);
Debug.WriteLine("M2.B");
}
delegate Task MyDel();
async void button_Click(object sender, RoutedEventArgs e)
{
MyDel del = null;
del += M1;
del += M2;
await del();
}
The output is:
M1.A
M2.A
M2.B
M1.B
That is, both invocation members go off simultaneously, not awaiting each other. I need them await each other so the output would be:
M1.A
M1.B
M2.A
M2.B
I tried this in place of await del():
foreach (MyDel member in del.GetInvocationList())
{
await member();
}
This works. However, I have lots of code places where this needs to be done. Delegates can have different number of parameters of various types but they all return Task.
How can I write an extension method which will let me run the code above by making calls like this?
del0.AwaitOneByOne(); // del0 is 'delegate Task Method()'
del1.AwaitOneByOne(paramInt1, paramStr2); // del1 is 'delegate Task Method(int, string)'
del2.AwaitOneByOne(paramBytes1); // del2 is 'delegate Task Method(byte[])'
If you use Func for you delegates rather than custom delegates you could write something like this:
public static class FuncHelper
{
public static async Task RunSequential<T1>(this Func<T1,Task> del, T1 param1)
{
foreach (var d in del.GetInvocationList().OfType<Func<T1, Task>>())
{
await d(param1);
}
}
public static async Task RunSequential<T1, T2>(this Func<T1, T2, Task> del, T1 param1, T2 param2)
{
foreach (var d in del.GetInvocationList().OfType<Func<T1, T2, Task>>())
{
await d(param1, param2);
}
}
// Additional methods for more parameters go here
}
It does seem that you are trying to use delegates in ways they were not really intended. They aren't really supposed to control order or have the functions rely on each other to complete.
Probably better off making a custom collection, maybe override += and -= if you want some delegate like behavior.
The cause of your problem is that your delegates have a different set of parameters.
The solution is to create an extra delegate that contains the call inclusive the parameters, similar to the System.Windows.Forms.MethodInvoker delegate.
The only difference in your methodInvoker is that your methodInvoker is not a delegate that returns void, but a delegate that returns a Task.
The function in your extension class would be similar to your foreach:
public delegate task MethodInvoker();
static class DelegateExtensions
{
public static async Task ExecuteDelegates(this IEnumerable<MethodInvoker> methodInvokers)
{
foreach (var methodInvoker in methodInvokers)
{
await methodInvoker();
}
}
}
Usage would be like:
public MyClass
{
private async Task F1()
{
Debug.WriteLine("Begin F1");
await Task.Delay(TimeSpan.FromSeconds(1));
Debug.WriteLine("F1 Completed");
}
private async Task F2(TimeSpan waitTime)
{
Debug.WriteLine("Begin F2");
await Task.Delay(waitTime);
Debug.WriteLine("F2 Completed");
}
private async Task F3(int count, TimeSpan waitTime)
{
Debug.WriteLine("Begin F3");
for (int i = 0; i < count; ++i)
{
await Task.Delay(waitTime);
}
Debug.WriteLine("F3 Completed");
}
}
public async Task ExecuteMyFunctions()
{
MyClass X = new MyClass();
IEnumerable<MethodInvoker> myMethodInvokers = new MethodInvoker[]
{
() => X.F1(),
() => X.F2(TimeSpan.FromSeconds(1)),
() => X.F3(4, TimeSpan.FromSeconds(0.25)),
}
await myMethodInvokers.ExecuteDelegates();
}

Task.Run Ambiguous Parameter Overloads

I'm using the Task class in C# and want to pass a predefined method that returns a value and not using lambdas to the Task.Run method.
Here is a console app with the code:
static int ThreadMethod()
{
return 42;
}
static void Main(string[] args)
{
Task<int> t = Task.Run(function:ThreadMethod);
WriteLine(t.Result);
}
However, it is returning this error:
The call is ambiguous between the following methods or properties: 'Task.Run<TResult>(Func<TResult>)' and 'Task.Run(Func<Task>)'
I tried doing this to fix it and got my expected result:
Task<int> t = Task.Run((Func<int>)ThreadMethod);
However, I am not sure if I'm doing it right or are there any better solution?
Fix your .Run argument like in this example. Can be copied and pasted into LinqPad to test.
public static void Main(string[] args)
{
Task<int> t = Task.Run(() => ThreadMethod());
WriteLine(t.Result);
}
public static int ThreadMethod()
{
return 42;
}
If you want to see it as a variable to pass check out below:
public static void Main(string[] args)
{
//Func<int> is saying I want a function with no parameters
//but returns an int. '() =>' this represents a function with
//no parameters. It then points to your defined method ThreadMethod
//Which fits the notions of no parameters and returning an int.
Func<int> threadMethod = () => ThreadMethod();
Task<int> t = Task.Run(threadMethod);
Console.WriteLine(t.Result);
}
public static int ThreadMethod()
{
return 42;
}
Here is the Documentation on Func(T), on the left hand menu you can select the different variations of Func() objects.

Overload resolution and async await

Below code gives error CS0121,
The call is ambiguous between the following methods or properties: 'RunTask(System.Func<System.Threading.Tasks.Task>)' and 'RunTask(System.Action)'
static void RunTask(Func<Task> intTask)
{
}
static void RunTask(Action voidTask)
{
}
static async Task DoAsyncTask()
{
await Task.Delay(500);
}
public static void Main(string[] args)
{
var asyncTask = new Func<Task>(DoAsyncTask);
RunTask(DoAsyncTask);
}
But below code can compile
static void RunTask(Func<Task> intTask)
{
}
static void RunTask(Action voidTask)
{
}
static async Task DoAsyncTask()
{
await Task.Delay(500);
}
public static void Main(string[] args)
{
var asyncTask = new Func<Task>(DoAsyncTask);
RunTask(asyncTask);
}
Why so?
The C# compiler does not take return type of a delegate into account when trying to decide the best overloaded method that takes a delegate.
Also see this question

Categories