Task.Factory.StartNew Passing return values - c#

i gote the following method and i want to pass the return values of the dosleep method:
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew(() => dosleep(2000));
var t2 = Task.Factory.StartNew(() => dosleep(1000));
Task.WaitAll(t1,t2);
Console.WriteLine("All Done in {0} milliseconds!"); //t1+t2 here!!
}
public static int dosleep(int Milliseconds)
{
System.Threading.Thread.Sleep(Milliseconds);
Console.WriteLine("Task finished");
return Milliseconds;
}

Use the Result property of the Task object
Console.WriteLine("All Done in {0} milliseconds!", t1.Result + t2.Result);

Related

Cast a function as variable

Let be the following function Measure for measurement of execution time for some functnion method
public static TimeSpan Measure(Action method)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
method.Invoke();
stopwatch.Stop();
return stopwatch.Elapsed;
}
This method is launched by the following line of code
var ExecTime = ComplexityCounters.Measure(() => method(int a, int b));
As we can see it's a very huge recall of Measure, so, let's try to short it by the following function
public static TimeSpan ExecTime (Action method)
{
var ExecutionTime = Measure(() => method.Invoke());
return ExecutionTime;
}
But
var ExecTime = ExecTime(method(int a, int b));
gives the error c# cannot convert from 'void' to 'System.Action'. How to fix it ? Or may be is there a way to compose those two function in one ?
here full example
public static TimeSpan Measure(Action method)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
method.Invoke();
stopwatch.Stop();
return stopwatch.Elapsed;
}
public static TimeSpan ExecTime(Action method)
{
var ExecutionTime = Measure(() => method.Invoke());
return ExecutionTime;
}
private static void Main(string[] args)
{
var spentTime = ExecTime(() => Sum(1,2));
}
public static int Sum(int t1, int t2)
{
return t1 + t2;
}
actually you are declaring your variable ExecTime same as your method name ExecTime

Task.WaitAll with CancelationToken

I need to execute many methods at the same time and the result of all, concatenate them in a single list. In the following example, I wait 3 seconds for each method, but in one of them I added a sleep (10 seconds) to check the result and it is not the expected one. The method never cancels and waits for those 10 seconds. What is the problem? Thank you!
var result = await Task.Run(() => Load<MyCustomClass>(OneMethod(), OtherMethod()));
private List<T> OneMethod()
{
return new List<T>();
}
private List<T> OtherMethod()
{
Thread.Sleep(10000);
return new List<T>();
}
private async Task<List<T>> Load<T>(params List<T>[] taskList)
{
try
{
return (await Task.WhenAll(taskList.Select(x =>
Task.Run(() => x, new CancellationTokenSource(3000).Token)))).SelectMany(x => x).ToList();
}
catch (Exception currentException)
{
//BLA BLA BLA
}
return new List<T>();
}
You must pass the CancellationToken to the methods and check if cancellationToken is requested or directly raise an exception.
var t = new CancellationTokenSource(3000).Token
var result = await Task.Run(() => Load<MyCustomClass>(OneMethod(t), OtherMethod(t)));
private List<T> OneMethod(CancellationToken t)
{
token.ThrowIfCancellationRequested();
return new List<T>();
}
private List<T> OtherMethod(CancellationToken t)
{
Thread.Sleep(10000);
token.ThrowIfCancellationRequested();
// or you can check if cancellation is requested
// if (token.IsCancellationRequested) ...
return new List<T>();
}
private async Task<List<T>> Load<T>(params List<T>[] taskList)
{
try
{
return (await Task.WhenAll(taskList.Select(x =>
Task.Run(() => x)))).SelectMany(x => x).ToList();
}
catch (Exception currentException)
{
//BLA BLA BLA
}
return new List<T>();
}
See this question

Propagating Exceptions from Task.ContinueWith?

In the following program, how do I propagate the OverflowException to Main?
class Program
{
static readonly CancellationTokenSource Source = new CancellationTokenSource();
static void Main(string[] args)
{
CallDoSomething(1);
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}
static void CallDoSomething(int foo)
{
var task = Task.Factory.StartNew(() => DoSomething(foo), Source.Token);
task.ContinueWith(t =>
{
var result = task.Result;
Console.WriteLine(result);
Thread.Sleep(500);
CallDoSomething(result);
}, TaskContinuationOptions.NotOnCanceled);
task.ContinueWith(t => t.Exception?.Handle(ex => throw ex), TaskContinuationOptions.OnlyOnFaulted);
}
static int DoSomething(int foo)
{
if (foo > 100)
{
Source.Cancel();
throw new OverflowException("foo overflowed");
}
return foo * 2;
}
}

Generic function declaration in C#

I'm trying to create some stats about method call duration in a library.
Instead of wrapping each method call to the library with lines to time and track it, I want to create a generic action and function which does these recurring steps.
E.g. for methods that don't return a value, I have created this:
private readonly Action<string, Action> timedAction = (name, action) =>
{
var sw = Stopwatch.StartNew();
action.Invoke();
trackDuration(name, sw.ElapsedMilliseconds);
};
That can be invoked with timedAction("methodname", () => lib.methodname()).
I want to do something similar for methods that return a value, but obviously Action can't be used for that purpose, since it can't return a value.
Is there a way to do this with a generic Func, so I don't have to declare one for each combination of library method parameters?
You can use a generic function like this:
private static TValue FuncHandler<TValue>(string name, Func<TValue> func)
{
var sw = Stopwatch.StartNew();
var result = func();
trackDuration(name, sw.ElapsedMilliseconds);
return result;
}
Call it like this:
var result = FuncHandler("name", () => MyMethod(param1));
Indeed, AOP will buy you more than this sort of tediousness:
https://dotnetfiddle.net/5PLCmM
// Needs to be replicated after Func<T1, TResult>, Func<T1, T2, TResult>, etc, for all the functions arities you'll want to wrap with it
public static TResult Timed<T1, /*T2, etc*/TResult>(out long duration, Func<T1, /*T2, etc*/TResult> func, T1 arg1/*T2 arg2, etc*/)
{
//start timing
var t0 = DateTime.Now;
var result = func(arg1/*, arg2, etc*/);
//end timing
duration = (long)DateTime.Now.Subtract(t0).TotalMilliseconds;
return result;
}
public int Factorial(int n)
{
return n > 0 ? n * Factorial(n - 1) : 1;
}
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n - 2) + Fibonacci(n - 1) : n;
}
public static void Main()
{
var program = new Program();
long duration;
var _12bang = Timed(out duration, program.Factorial, 12);
Console.WriteLine("{0}! = {1} in {2} ms", 12, _12bang, duration);
var fib31 = Timed(out duration, program.Fibonacci, 31);
Console.WriteLine("Fib {0} = {1} in {2} ms", 31, fib31, duration);
}
(yes, I know about StopWatch; was just too lazy to put it in there)
'Hope this helps.
In your case AOP will be more tedious. Here is my solution which works:
Class1.cs
using System;
namespace ClassLibrary1
{
public class Class1
{
public void WriteNoParam()
{
Console.WriteLine("void");
}
public void WriteWithParam(string name)
{
Console.WriteLine("My name is: " + name);
}
}
}
Program.cs
using System;
namespace ConsoleApplication2
{
using System.Diagnostics;
using System.Reflection;
using ClassLibrary1;
class Program
{
static void Main(string[] args)
{
var prReflection = new TestReflection<Class1>();
var elapsed = prReflection.TestFunc(new Class1(), #"C:\Users\yasir\Documents\visual studio 2013\Projects\ConsoleApplication2\ClassLibrary1\bin\Debug\ClassLibrary1.dll", "WriteNoParam", new string[0]);
Console.WriteLine("Elapsed time for non parameter method: "+elapsed);
elapsed = prReflection.TestFunc(new Class1(), #"C:\Users\yasir\Documents\visual studio 2013\Projects\ConsoleApplication2\ClassLibrary1\bin\Debug\ClassLibrary1.dll", "WriteWithParam", new[]{"Yasir"});
Console.WriteLine("Elapsed time for parameter method: " + elapsed);
Console.ReadLine();
}
}
public class TestReflection<T> where T: class
{
public Func<T, string, string, string[], long> TestFunc = (arg1, s, s2, arr) =>
{
var assembly = Assembly.LoadFile(s);
var type = assembly.GetType(typeof (T).ToString());
long executionTime;
if (type != null)
{
var methodInfo = type.GetMethod(s2);
if (methodInfo != null)
{
ParameterInfo[] parameters = methodInfo.GetParameters();
object classInstance = Activator.CreateInstance(type, null);
var stopWatch = new Stopwatch();
if (parameters.Length == 0)
{
// This works fine
stopWatch.Start();
methodInfo.Invoke(classInstance, null);
return stopWatch.ElapsedMilliseconds;
}
stopWatch.Start();
methodInfo.Invoke(classInstance, arr); ;
return stopWatch.ElapsedMilliseconds;
}
}
return 0;
};
}
}
I have run in debug mode to test if the console is able to output in milliseconds and it works.
If you don't run in debug, execution will be really fast and console will output 0.
I know this question already has an answer, but I think this solution can be interesting, if you don't want to have to pass the name, yourself, each time, you could do this:
(It was a lot inspired by #selami' answer.)
private MemberInfo GetMethodName<T>(Expression<T> expression)
{
Expression body = expression.Body;
// You might want to complete this
// depending on which expression you want to use
return ((MethodCallExpression)body).Method.Name;
}
// Works for both Action and Func
private object TimedMethodInvoke<T>(Expression<T> funcExpression)
{
var sw = Stopwatch.StartNew();
var result = ((Delegate)(object)funcExpression.Compile()).DynamicInvoke();
trackDuration(GetMethodName(funcExpression), sw.ElapsedMilliseconds);
return result;
}
And your final methods:
public void TimeMethod(Expression<Action> actionExpression)
{
TimedMethodInvoke(actionExpression);
}
public TValue TimeMethod<TValue>(Expression<Func<TValue>> funcExpression)
{
return (TValue)TimedMethodInvoke(funcExpression);
}
I didn't run a benchmark over this solution, but I guess you should encounter a little performance hit, but if you don't mind about that and want to avoid to type the name each time, this could help.

Returning values from threads

If I created a delegate to allow multiple parameters to be passed into the thread start method, as described in this answer, what would be the best way to return a value from the RealStart method to the method which starts the thread?
As I see it, my options are either to create a static variable.
private static Boolean result;
private static String message = "";
public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
var t = new Thread(() => RealStart(param1, param2));
t.Start();
return t;
}
private static void RealStart(SomeType param1, SomeOtherType param2) {
...
}
or to wrap the the delegate in a class
private class TestThread
{
public String message = "";
public Boolean result;
public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
var t = new Thread(() => RealStart(param1, param2));
t.Start();
return t;
}
private static void RealStart(SomeType param1, SomeOtherType param2) {
...
}
}
One issue I see with using a class is that it somewhat negates the point of passing parameters via the delegate as I could pass them into the class when I initialize it.
(Or the third option of not using it in this manner)
Could RealStart ever have a return type?
Are there any pros or cons to using either of the processes described, even if it just comes down to structure/organisation of code?
Use Task, and Task.Result:
// Return a value type with a lambda expression
Task<int> task1 = Task<int>.Factory.StartNew(() => 1);
int i = task1.Result;
// Return a named reference type with a multi-line statement lambda.
Task<Test> task2 = Task<Test>.Factory.StartNew(() =>
{
string s = ".NET";
double d = 4.0;
return new Test { Name = s, Number = d };
});
Test test = task2.Result;
You can use Actions too (for updating form components...):
public TextBox foo = new TextBox();
foo.Text = "foo";
.
.
.
Thread t = new Thread(() => FooBar(p1, p2) );
t.Start();
public void FooBar(Parm parm1, Parm parm2)
{
...
this.foo.BeginInvoke(new Action(() => foo.Text = "bar"));
}

Categories

Resources