Оператор блокировки C# позволяет только одному потоку обращаться к объекту за раз. В цикле Parallel.ForEach не было бы быстрее создавать новый объект (локальную переменную) внутри цикла, а не использовать переменную поля, так как в этом случае нити никогда не блокируются? Какими будут плюсы/минусы каждого из них?Блокировка потоков против создания нового объекта
Я использую приведенный ниже код, кажется, что создание локального var вместо использования блокировки в поле немного быстрее.
nb. В переменной 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);
});
Если ваш общий объект имеет какую-то уникальную информацию о состоянии, о которой вы заботитесь, то вы не можете просто создавать новые. –
И если я правильно помню, TPL также поддерживает локальные переменные потока в своих циклах. – Dirk
Общепринято избегать постоянного создания тяжелых объектов и потоков, создавая пул потоков, которые создают «тяжелый» при запуске, а затем обходят очередь пула, выталкивая данные для «тяжелого». Иными словами, я бы, вероятно, не использовал ни одну из ваших альтернатив. –