Is there any example of executing real tasks?
My need is very simple: I want to execute a function in a new thread, passing some parameters and taking the result.
Cheers
Is there any example of executing real tasks?
My need is very simple: I want to execute a function in a new thread, passing some parameters and taking the result.
Cheers
Hi,
I put an example in
https://src.springframework.org/svn/...ple/Program.cs
The essence of it is
Cheers,Code:IExecutorService executorService = Executors.NewFixedThreadPool(THREAD_POOL_SIZE); var list = new List<IFuture<long>>(); for (int i = 0; i < 20000; i++) { SumNumbers sumNumbers = new SumNumbers(100 + i); IFuture<long> submit = executorService.Submit<long>(sumNumbers.CalculateSum); list.Add(submit); } // This will make the executor accept no new threads // and finish all existing threads in the queue executorService.Shutdown(); long sum = 0; foreach (var future in list) { sum += future.GetResult(); } Console.WriteLine("Sum = " + sum); Console.WriteLine("Hit return to exit"); Console.ReadLine();
Mark
Hi,
I also implemented an example based on some Parallel Task library tutorial I ran across. Might be useful to compare.
MarkCode:IExecutorService executorService = Executors.NewFixedThreadPool(THREAD_POOL_SIZE); IFuture<int> f1 = executorService.Submit<int>(GenerateNumbers); IFuture<string> f2 = executorService.Submit<string>(PrintCharacters); IFuture<int> f3 = executorService.Submit<int>(PrintArray); Console.WriteLine("Numbers generated till {0}", f1.GetResult()); Console.WriteLine("Original String {0}", f2.GetResult()); Console.WriteLine("Array Count {0}", f3.GetResult());
Thanks very much, Mark!
So, the correct way (or, at least, one correct way) to answer to my original question, calling a function with parameters and taking the result, can be the following:
where the method SumNumbers2.CalculateSum has some parameters:Code:MethodCaller caller = new MethodCaller(new SumNumbers2(), typeof(SumNumbers2).GetMethod("CalculateSum"), new object[] { 100000 }); IExecutorService executorService = Executors.NewSingleThreadExecutor(); IFuture<object> call = executorService.Submit<object>(caller.MakeCall); executorService.Shutdown(); object result = call.GetResult(TimeSpan.FromSeconds(5));
and the helper class MethodCaller takes care of the real call with input parameters and result value:Code:public class SumNumbers2 { public long CalculateSum(int max) { long sum = 0; for (int i = 1; i < max; i++) { sum += i; } return sum; } }
Code:public class MethodCaller { private object _target; private MethodInfo _method; private object[] _arguments; public MethodCaller(object target, MethodInfo method, object[] arguments) { this._target = target; this._method = method; this._arguments = arguments; } public object MakeCall() { return _method.Invoke(_target, _arguments); } }
Cheers
Hi,
You should use a lambda expression this way you can effectively use Action<T1>, Action<T1, T2>, etc, or Func<TResult>, Func<T, TResult> to the methods args of Submit that expect just Action and Func<T>. I've updated the examples in subversion. TAke a look but here is a snippit.
where SumNumbers2Code:// Call with method arguments for (int i = 0; i < 20000; i++ ) { SumNumbers2 sumNumbers2 = newSumNumbers2(); int i1 = i; // copy to local variable for closure. IFuture<long> submit = executorService.Submit(() => sumNumbers2.CalculateSumWithArgsAndReturnValue(100 + i1)); futures.Add(submit); }
Give that a shot...Code:public class SumNumbers2 { public long CalculateSumWithArgsAndReturnValue(int max) { long sum = 0; for (int i = 1; i < max; i++) { sum += i; } return sum; } }
Mark
Mark, thanks for the hint.
My situation is slightly different: I have to call a method of an object and each of them isn't known a priori, they will be specified at runtime.
In particular I'm in an IMethodInterceptor on a fake object, having an IMethodInvocation and an object to make the real call on.
So, I think the MethodCaller approach can be good.
Cheers
Hi,
The reflection approach seems what you need then. What version of .NET are you on? I see your MethodCaller uses standard reflection, which maybe slow for you. If performance is an issue you can speed this up in a couple ways.
I took this as an opportunity to use ExpressionTrees for creating the dynamic code to invoke methods. Here are some variations you can use to make your MethodCaller implementation more performante. Note, that Spring's IDynamicMethod generates IL (so good for .NET 2.0/3.0).
Code://Say this was created at runtime and we don't know the type or parameter values at compile time. object obj = new SumNumbers2(); object[] parameters = new object[] {100}; //Find the method we want to invoke MethodInfo methodInfo = ReflectionUtils.GetMethod(obj.GetType(), "CalculateSumWithArgsAndReturnValue", ReflectionUtils.GetTypes(parameters)); //Use expression trees to generate code to invoke method and assign to a delegate. LateBoundMethod methodCallback = DelegateFactory.Create(methodInfo); IFuture<object> futureLong = executorService.Submit(() => methodCallback(obj, parameters)); var result = futureLong.GetResult(); Console.WriteLine("LateBoundMethod Style : Result = " + result); ///Use Spring's IL generation to invoke method dynamically. IDynamicMethod method = DynamicMethod.Create(methodInfo); IFuture<object> futureLongViaDM = executorService.Submit(() => method.Invoke(obj, parameters)); var resultViaDM = futureLongViaDM.GetResult(); Console.WriteLine("Spring's IDynamicMethod Style: Result = " + resultViaDM);
I've updated the repo with this. The ReflectionUtils class comes from Spring.Core. The magic with Expression trees is thanks to Nate Kohari here. Nate's post says
So you probably want to go with Spring's DynamicMethod approach as it is based on generating IL.Note: After working with expression trees further, I’ve found that generating CIL by hand is dramatically faster than using expression trees. Still, this is an interesting concept, and I’ve kept this post here for posterity.
Cheers,
Mark
Last edited by Mark Pollack; 06-25-2010 at 03:27 PM. Reason: now saw how MethodCaller was implemented....