如何解决带有记录和锁的异步实现
我担心我的代码中出现竞争条件。
我有这个从数据库中获取信息的函数:
public async Task ExecuteBroadcasts()
{
List<Broadcast> broadcasts =_iSMSFetcherUnitOfWork.GetAllBroadCastsInPastTimeThatDidntRun();
foreach (Broadcast broadcast in broadcasts)
{
foreach (SenderPhone sender in broadcast.SenderPhoneList.SenderPhones)
{
foreach (ReceiverPhone receiverPhone in broadcast.RecipeintPhoneList.ReceiverPhones)
{
var tasks= broadcast.RecipeintPhoneList.ReceiverPhones.Select(receiverPhone => _iSMSProcessorAndSender.ProcessSMSes(new PreProcessedSMS(sender.Phone,receiverPhone,broadcast.SMSTemplate))).ToArray();
await Task.WhenAll(tasks);
}
}
}
}
这种类型的“PreProcessedSMS”是一条记录。 ProcessSMSes 是一个函数,它发送从数据库中获取的信息并通过 SMS 提供程序发送。这是这个函数的内容。
public async Task ProcessSMSes(PreProcessedSMS preProcessedSMS)
{
_iSMSExpressionInterpreter.ReceiverPhone = preProcessedSMS.receiverPhoneObj;
object sync = new object();
string smsBody = string.Empty;
lock (sync) smsBody = preProcessedSMS.sMSTemplate;
Task longRunning = Task.Factory.StartNew(() =>
{
smsBody = _iSMSExpressionInterpreter.TranslateSpinner(preProcessedSMS.sMSTemplate);
});
await longRunning.ContinueWith(async (sms) =>
{
smsBody = _iSMSExpressionInterpreter.TranslateFirstName(smsBody);
smsBody = _iSMSExpressionInterpreter.TranslateLastName(smsBody);
smsBody = _iSMSExpressionInterpreter.TranslateCustom(smsBody);
smsBody = _iSMSExpressionInterpreter.TranslateUnsubscribe(smsBody);
await _iSMSDispatcher.SendSMS(new SMSRecord(preProcessedSMS.senderPhone,preProcessedSMS.receiverPhoneObj.Phone,smsBody));
},TaskContinuationOptions.NotOnFaulted);
longRunning.Start();
}
我锁定了 'smsBody' 参数,因为担心会执行下一个函数,为其设置不同的值。我对实施持谨慎态度。在不遇到可能的竞争条件的情况下有效执行代码的最佳方法是什么。
更新:
public async Task ProcessSMSes(PreProcessedSMS preProcessedSMS)
{
await Task.Run(async () =>
{
_iSMSExpressionInterpreter.ReceiverPhone = preProcessedSMS.receiverPhoneObj;
string smsBody = _iSMSExpressionInterpreter.TranslateSpinner(preProcessedSMS.sMSTemplate);
smsBody = _iSMSExpressionInterpreter.TranslateFirstName(smsBody);
smsBody = _iSMSExpressionInterpreter.TranslateLastName(smsBody);
smsBody = _iSMSExpressionInterpreter.TranslateCustom(smsBody);
smsBody = _iSMSExpressionInterpreter.TranslateUnsubscribe(smsBody);
await _iSMSDispatcher.SendSMS(new SMSRecord(preProcessedSMS.senderPhone,smsBody));
});
}
解决方法
lock
仅在其他所有内容也使用相同的 lock
时才有效。在这种情况下,您锁定了一个局部变量,它什么也不做。您不能使用锁来防止任何其他代码更改任何内容。在这种情况下,您可以在 lock
的实现中使用 sMSTemplate
以便每次读取/写入时都使用 lock
,但这似乎非常奇怪的。我建议明智地使用锁,其中预期多线程访问,而不是“出于恐惧”。
附注:
-
Don't use
Task.Factory.StartNew
;如果您想在线程池线程上运行代码,请使用Task.Run
。 -
Don't use
ContinueWith
;改用await
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。