-1

I have a question of understanding. Which is the better option in terms of safety and performance?

private ConcurrentDictionary<string, ProfitTarget> chartTraderTP;

if (chartTraderTP.ContainsKey(orderId))
{
    //Store values for later use in Mouse Events
    chartTraderTP[orderId].OrderLabelRectText = rectTextOrderLabelTP;
    //We can draw the Rectangle based on the TextLayout used above
    if (!chartTraderTP[orderId].IsMovingOrder
        && (ChartTraderDisplayStyle == ChartTraderDisplayStyle.Own
            || ChartTraderDisplayStyle == ChartTraderDisplayStyle.Both))
    {
        RenderTarget.FillRectangle(rectTextOrderLabelTP, tpAreaBrushDx);
        RenderTarget.DrawRectangle(rectTextOrderLabelTP, tpOutlineBrushDx,
            LabelOutlineWidthTP);
        RenderTarget.DrawTextLayout(vectText, tpTextLayout, tpTextBrushDx,
            SharpDX.Direct2D1.DrawTextOptions.NoSnap);
    }
}

or

private ConcurrentDictionary<string, ProfitTarget> chartTraderTP;
//Store values for later use in Mouse Events
if (chartTraderTP.ContainsKey(orderId))
{
    chartTraderTP[orderId].OrderLabelRectText = rectTextOrderLabelTP;
}
//We can draw the Rectangle based on the TextLayout used above
if (chartTraderTP.ContainsKey(orderId) && !chartTraderTP[orderId].IsMovingOrder
    && (ChartTraderDisplayStyle == ChartTraderDisplayStyle.Own
        || ChartTraderDisplayStyle == ChartTraderDisplayStyle.Both))
{
    RenderTarget.FillRectangle(rectTextOrderLabelTP, tpAreaBrushDx);
    RenderTarget.DrawRectangle(rectTextOrderLabelTP, tpOutlineBrushDx,
        LabelOutlineWidthTP);
    RenderTarget.DrawTextLayout(vectText, tpTextLayout, tpTextBrushDx,
        SharpDX.Direct2D1.DrawTextOptions.NoSnap);
}

The code is executed very often, and I would like to make the access as fast as possible but still threadsafe.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Sidlercom
  • 11
  • 4
  • 1
    I would advise to use `var found = chartTraderTp.TryGetValue(orderId, out var profitTarget);` and if it's found work with the instance you retrieved. –  Mar 02 '21 at 17:32
  • @Knoop That assumes no other threads are editing the objects in the collection, which doesn't seem to be the case. – Servy Mar 02 '21 at 17:33
  • 1
    @Servy that's true, but then you just need to lock the object you retrieved instead of the entire `Dictionary`. It's hard to say anything specific without more information about what different threads are doing. –  Mar 02 '21 at 17:34
  • @Knoop But now you're taking out multiple different locks, which increases complexity quite a bit. It may be needed, it may not be, but saying they can just use `TryGetValue` and be done is pretty unlikely to be the case. – Servy Mar 02 '21 at 17:37

2 Answers2

2

Neither are safe, as you're performing multiple operations while assuming the collection isn't changing between operations, which is not a safe assumption.

Since you want to use a number of different operations and need entire section to be logically atomic, just use a regular Dictionary and lock around the access to it.

Servy
  • 202,030
  • 26
  • 332
  • 449
-3
   lock (chartTraderTP)
            {
                //Store values for later use in Mouse Events
                chartTraderTP[orderId].OrderLabelRectText = rectTextOrderLabelTP;
                //We can draw the Rectangle based on the TextLayout used above
                if (!chartTraderTP[orderId].IsMovingOrder && (ChartTraderDisplayStyle == ChartTraderDisplayStyle.Own || ChartTraderDisplayStyle == ChartTraderDisplayStyle.Both))
                {
                    RenderTarget.FillRectangle(rectTextOrderLabelTP, tpAreaBrushDx);
                    RenderTarget.DrawRectangle(rectTextOrderLabelTP, tpOutlineBrushDx, LabelOutlineWidthTP);
                    RenderTarget.DrawTextLayout(vectText, tpTextLayout, tpTextBrushDx, SharpDX.Direct2D1.DrawTextOptions.NoSnap);
                }
            }
Sidlercom
  • 11
  • 4
  • Using lock on a `ConcurrentDictionary` negates all its advantages, while preserving its disadvantages (awkward API, overhead). If you have to `lock`, you'd better do it on a normal `Dictionary` instead. – Theodor Zoulias Mar 03 '21 at 00:06