【发布时间】:2014-01-06 18:43:55
【问题描述】:
我正在 .net 项目 3.5 上实施生产者/消费者方法
只有一个生产者和一个消费者在各自的线程上运行
CheckOrderToProcess 方法检查符合特定条件的表并将它们添加到列表中(生产者)
bgOrdenes_DoWork 方法获取列表中的每个项目并执行一些逻辑(消费者)
我想避免锁定整个列表lstOrderToProcessto 以提高性能,我尝试使用ConcurrentQueue,但我无法升级到.net 4.0,因为这将用于不能升级到4.0
如何更改此实现以提高性能?我不必是一个列表,只要它可以在线程之间共享,我可以在最后添加并获取第一个元素(队列)
public class DatabaseCache : ICacheDB
{
private static List<NotificacionOrdenes> lstOrderToProcess;
private static Object lockOrders;
private static BackgroundWorker bgOrdenes;
private static bool pendingOrders = false;
private static Timer timerCheck;
public DatabaseCache(string eventSourceName, bool monitorearOrderNotifications)
{
bgOrdenes = new BackgroundWorker();
bgOrdenes.DoWork += new DoWorkEventHandler(bgOrdenes_DoWork);
lstOrderToProcess = new List<NotificacionOrdenes>();
lockOrders = new Object();
CheckOrderToProcess();
if (!bgOrdenes.IsBusy)
{
bgOrdenes.RunWorkerAsync();
}
//execute CheckOrderToProcess periodically
timerCheck = new Timer(2000);
timerCheck.Elapsed += new ElapsedEventHandler(timerCheck_Elapsed);
timerCheck.Enabled = true;
timerCheck.AutoReset = true;
}
void timerCheck_Elapsed(object sender, ElapsedEventArgs e)
{
CheckOrderToProcess();
}
private void CheckOrderToProcess()
{
DataSet ds;
NotificacionOrdenes notif;
ds = Data.GetOrderNotifications_ToProcess();
//if there is new info to process
if ((ds != null) && (ds.Tables[0].Rows.Count != 0))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
notif = new NotificacionOrdenes();
//fill NOTIF with info of each row
lock (lockOrders)
{
lstOrderToProcess.Add(notif);
}
}
pendingOrders = true;
}
}
void bgOrdenes_DoWork(object sender, DoWorkEventArgs e)
{
NotificacionOrdenes notif;
while (true)
{
if (pendingOrders)
{
lock (lockOrders)
{
notif = lstOrderToProcess[0];
lstOrderToProcess.RemoveAt(0);
//check to see if there is any pending order
pendingOrders = lstOrderToProcess.Any();
}
//Execute rest of the logic
}
}
}
}
【问题讨论】:
-
我看到您的计时器每 2 秒执行一次 - 这比锁定的时间复杂度要高出几个数量级。有许多改进的空间(基本上通过使用数组和互锁操作自己实现线程安全的无锁结构) - 但我怀疑这将是纯粹的过早优化。您确定锁定语句中存在高争用或性能瓶颈吗?如果您不确定,我宁愿将额外的时间花在分析上,而不是进行任意优化。
-
@Jan 在某些时候,我确实将 2000 毫秒更改为 100 毫秒,这让性能变得更糟。我从来没有实现过自己的联锁操作,但我敢打赌那里有一个库,我可以重复使用而不是重新发明轮子。
标签: c# .net multithreading .net-3.5