Whats wrong in this Parallel.For Code?

2020-05-07 08:51发布

问题:

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

回答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) => {}
            );