Out*_*ill 8 .net c# resharper multithreading
背景
我们的应用程序发送在数据库表中排队的电子邮件.我们发送了一些重复电子邮件的实例,所以我实现了一个锁,以防止多个线程同时发送电子邮件.
ReSharper警告我:
该字段有时在同步块内使用,有时在没有同步的情况下使用
题
为什么ReSharper告诉我这个,为什么我会担心它?
码
这是我的(删节)代码:
private readonly IMailQueueRepository _mailQueueRepository = new MailQueueRepository();
private static object _messageQueueLock = new object();
public void SendAllQueuedMessages(IPrincipal caller)
{
lock (_messageQueueLock) // Prevent concurrent callers
{
var message = _mailQueueRepository.GetUnsentMessage();
while (message != null)
{
SendQueuedMessage(message);
message = _mailQueueRepository.GetUnsentMessage();
}
}
}
public void SendQueuedMessage(IMessage message)
{
// I get the ReSharper warning here on _mailQueueRepository
var messageAttachments = _mailQueueRepository.GetMessageAttachments(message.Id);
// etc.
}
Run Code Online (Sandbox Code Playgroud)
ReSharper无法告知(或保证)SendQueuedMessage()
仅在同步块内调用.因此,就其而言,其他代码可能会在SendQueuedMessage()
没有同步的情况下调用,并且_mailQueueRepository
正在使用中SendQueuedMessage()
.
如果您确定没有其他代码(在包含类的内部或外部)调用此方法,或者您已确保类中的所有调用SendQueuedMessage()
也使用相同的锁对象进行同步,那么您就可以了.如果你班级以外没有其他代码真的需要这种方法,我建议你把它变成私有的.
问题场景:
我们已经发送了一些重复电子邮件的实例,因此我正在实现一个锁定,以防止多个线程同时发送电子邮件。
因此,您正在使用它Lock()
来防止这种情况的发生,这意味着您需要同步访问公共资源的线程。 _mailQueueRepository
但同样,您使用的相同代码中_mailQueueRepository
没有Lock
// I get the ReSharper warning here on _mailQueueRepository
var messageAttachments = _mailQueueRepository.GetMessageAttachments(message.Id); // <== Accessed without a lock
Run Code Online (Sandbox Code Playgroud)
因此,警告您以两种不同的形式访问您的宝贵资源是一种警告:一种synchronized
(线程安全)和另一种non-synchronized
(非线程安全)。
这是一个警告,告知您 (或让您识别)此矛盾的资源使用可能引起的问题。您可以选择全部使用(使用和警告将消失),也可以选择不参加比赛。_mailQueueRepository
_mailQueueRepository
synchronized
lock
另外,您可能会考虑以重新构造代码的方式,使用SendQueuedMessage()
从_mailQueueRepository
避免混合使用中提取的参数来调用您的代码。