Results 1 to 8 of 8

Thread: Simple example

  1. #1
    Join Date
    Apr 2008
    Posts
    45

    Default Simple example

    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

  2. #2
    Mark Pollack is offline Spring.NET Co-Lead Spring TeamSpring User
    Join Date
    Sep 2004
    Location
    New York, NY
    Posts
    1,683

    Default

    Hi,

    I put an example in

    https://src.springframework.org/svn/...ple/Program.cs

    The essence of it is
    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();
    
    Cheers,
    Mark

  3. #3
    Mark Pollack is offline Spring.NET Co-Lead Spring TeamSpring User
    Join Date
    Sep 2004
    Location
    New York, NY
    Posts
    1,683

    Default

    Hi,
    I also implemented an example based on some Parallel Task library tutorial I ran across. Might be useful to compare.

    Code:
    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());
    
    Mark

  4. #4
    Join Date
    Apr 2008
    Posts
    45

    Default

    Thanks very much, Mark!

  5. #5
    Join Date
    Apr 2008
    Posts
    45

    Default

    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:

    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));
    where the method SumNumbers2.CalculateSum has some parameters:

    Code:
    public class SumNumbers2
    {
        public long CalculateSum(int max)
        {
            long sum = 0;
            for (int i = 1; i < max; i++)
            {
                sum += i;
            }
            return sum;
        }
    }
    and the helper class MethodCaller takes care of the real call with input parameters and result value:

    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

  6. #6
    Mark Pollack is offline Spring.NET Co-Lead Spring TeamSpring User
    Join Date
    Sep 2004
    Location
    New York, NY
    Posts
    1,683

    Default

    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.

    Code:
    // 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); 
    }
    where SumNumbers2
    Code:
    public class SumNumbers2
    {
    public long CalculateSumWithArgsAndReturnValue(int max)
     {
       long sum = 0;
       for (int i = 1; i < max; i++)
       {
         sum += i;
       }
       return sum;
     } 
    }
    Give that a shot...

    Mark

  7. #7
    Join Date
    Apr 2008
    Posts
    45

    Default

    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

  8. #8
    Mark Pollack is offline Spring.NET Co-Lead Spring TeamSpring User
    Join Date
    Sep 2004
    Location
    New York, NY
    Posts
    1,683

    Default

    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
    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.
    So you probably want to go with Spring's DynamicMethod approach as it is based on generating IL.

    Cheers,
    Mark
    Last edited by Mark Pollack; 06-25-2010 at 03:27 PM. Reason: now saw how MethodCaller was implemented....

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •