0

this is the code that i want to run.

Parallel.For(1, itemCount, 1, () =>
                    {
                     return new ThreadLocalStateCache()
                     {
                         //assigning values to local variables
                         Receipient = serMailObj.ReceipientList.Dequeue(), //get a single recepeint for the email
                         mail = serMailObj.Email, //Object of type MailMessage
                         client = client //object of type SmtpClient
                     };
                }
     , (i, loopState) =>
     {
         doWork(i, loopState.ThreadLocalState);

     });
                }
//class to store local vairables for each thread
public class ThreadLocalStateCache
    {
        public KeyValuePair<string, string> Receipient { get; set; }

        public MailMessage mail { get; set; }

        public SmtpClient client { get; set; }
    }

private static void doWork(int instance, ThreadLocalStateCache threadInstance)
        { 
           //send mail
        }

and it keeps on saying

The type arguments for method 'System.Threading.Tasks.Parallel.For(long, long, System.Func, System.Func, System.Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

I could not find any resource on the internet that explains clearly how to use parallel.for with thread local variables. I am trying to process long list of email recipients and send mails to them. Please tell how can i use parallel.for.

EDIT 1: I am trying this code after reading this article http://www.lovethedot.net/2009/02/parallelfor-deeper-dive-parallel.html

Pankaj Kumar
  • 1,748
  • 6
  • 28
  • 41

1 Answers1

1

The Parallel.For overloads that take step as the third argument were removed from .NET 4; see comments to http://blogs.msdn.com/b/pfxteam/archive/2009/05/26/9641563.aspx.

Due to that, your call with 5 arguments is resolved to this overload:

For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32, ParallelLoopState, TLocal, TLocal>, Action<TLocal>)

And obviously the compiler cannot match types of the arguments.

Since the step is 1 anyway, just remove it.
Then you will need to fix the body delegate which must have three parameters (since thread local variable is now separate from loop state object), and add another delegate that will be applied to thread local variables for final computation. At the end, it should be something like this:

Parallel.For( 1, itemCount,
              () =>
              { return new ThreadLocalStateCache() 
                           { 
                               Receipient = serMailObj.ReceipientList.Dequeue(),
                               mail = serMailObj.Email,
                               client = client
                           }; 
              },
              (i, loopState, threadLocal ) => 
              { 
                  doWork(i, threadLocal);
                  return threadLocal;
              },
              (threadLocal) => {}
            );
Alexey Kukanov
  • 12,479
  • 2
  • 36
  • 55
  • thanks that works. could you please explain why the doWork method has a requirement to return a ThreadLocalStateCache object? if i try to return a void it starts showing compilation error. Why is it required to return an object of the type being returned in LocalInit? – Pankaj Kumar Apr 11 '11 at 11:03
  • @Pankaj: It's not doWork but the _body_ delegate that needs to return a thread local state object. The reason is that this object works as an accumulator of partial results passed between invocations of the body on the same thread. More info available at the MSDN page for Parallel.For. I fixed the code above. – Alexey Kukanov Apr 11 '11 at 12:17