C# lock 语句一次只允许一个线程访问一个对象。 在 Parallel.ForEach 循环中,在循环内创建一个新对象(局部变量)而不是使用字段变量会不会更快,因为那样不会阻塞任何线程? 每种方式的优缺点是什么?
我正在使用下面的代码,似乎创建本地变量而不是在字段上使用锁会稍微快一些。
注意。 toEmails 变量中有 3 个电子邮件字符串。
//Method 1 with lock statement takes 14092ms
List<string> toEmails = getListOfToEmails();
Object locker = new object();
SmtpClient smtpClient = getSmtpObject();//smtpClient is used here as a field
Parallel.ForEach(toEmails, toEmail =>
{
string emailBody = getEmailBody(toEmail);
MailMessage mailMessage = getMailMesssageObject(emailBody, toEmail);
lock (locker)
{
smtpClient.Send(mailMessage);
}
});
//Method 2 without lock statement (creating a new local var each iteration) takes 13947ms
List<string> toEmails = getListOfToEmails();
Parallel.ForEach(toEmails, toEmail =>
{
SmtpClient smtpClient = getSmtpObject();//smtpClient is used here as a local var
string emailBody = getEmailBody(toEmail);
MailMessage mailMessage = getMailMesssageObject(emailBody, toEmail);
smtpClient.Send(mailMessage);
});
最佳答案
使用 ForEach
的重载:
Parallel.ForEach(toEmails, () => getSmtpObject() , (toEmail, state, smtp) =>
{
SmtpClient smtpClient = smtp;
string emailBody = getEmailBody(toEmail);
MailMessage mailMessage = getMailMesssageObject(emailBody, toEmail);
smtpClient.Send(mailMessage);
return smtp;
}, smtp => {});
第二个参数是一个委托(delegate),您可以使用它来创建线程本地数据。在循环的每次迭代中,您将获得本地数据,您可以更改它并返回到下一次迭代。
最后一个参数是另一个将在每个任务结束时调用的委托(delegate)
关于c# - 线程锁定与创建新对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20931439/