0
  public class SystemBase
{
    ***private ConcurrentDictionary<string, ProfitTarget> dictTP = new ConcurrentDictionary<string, ProfitTarget>();***

    private void DrawOrderLineTP(Order order, ChartControl chartControl, ChartScale chartScale, string orderId, double openProfit, double tickValue)
    {
        RectangleF rectTextOrderLabelTP = new RectangleF(vectText.X - 2, vectText.Y, tpTextLayout.Metrics.Width + 4, tpTextLayout.Metrics.Height);

        ***var newValueText = new ProfitTarget { OrderLabelRectText = rectTextOrderLabelTP };***
        if (dictTP != null && newValueText != null)
        {
            dictTP.AddOrUpdate(orderId, newValueText, (key, oldValueText) =>
            {
                if (newValueText.OrderLabelRectText != oldValueText.OrderLabelRectText)
                    oldValueText.OrderLabelRectText = newValueText.OrderLabelRectText;

                //We can draw the Rectangle based on the TextLayout used above
                if (!dictTP[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);
                }
                //return oldValueText, since it should be updated, instead of being replaced
                return oldValueText;
            });
        }
    }
}

public class ProfitTarget : IEquatable<ProfitTarget>
{
    private RectangleF orderLabelRectText;


    [CLSCompliant(false)]
    public RectangleF OrderLabelRectText { get { return orderLabelRectText; } set { orderLabelRectText = value; } }
}

i would like to change the dictionary from above with the following:

private ConcurrentDictionary<string, Lazy<ProfitTarget>> dictTP = new ConcurrentDictionary<string, Lazy<ProfitTarget>>();

the "RectangleF rectTextOrderLabelTP " is to be brought up to date via the property in the other class "ProfitTarget", as it is now (AddOrUpdate). Unfortunately, I can't get the conversion from the conventional dictionary to the new Lazy to work, can anyone help me?

I want to make sure that everything is thread safe and that no "lock" is used, which is why I came across the possibility of using the Lazy on the web. with the code i have so far, sometimes get error messages like: "System.NullReferenceException" or "KeyNotFoundException".

Unfortunately, I'm a newbie in programming and always like to learn something new. I'm very grateful for any help!

Sidlercom
  • 11
  • 4
  • 1
    `Lazy` (typically) has nothing to do with making things thread-safe and this case is no exception. You are accessing the dictionary for the value to be updated *inside the function that has to deal with updating the value*. This is not allowed because calling the delegates for `AddOrUpdate` is not itself atomic (as the documentation notes). Use only `oldValueText` and `newValueText` and not `dictTP[orderID]`. Furthermore, UIs are typically single-threaded as well, so whether you can call things like `RenderTarget.FillRectangle` directly is questionable -- but that's another matter. – Jeroen Mostert Mar 08 '21 at 13:34
  • Take a look at this: [Is AddOrUpdate thread safe in ConcurrentDictionary?](https://stackoverflow.com/questions/39156752/is-addorupdate-thread-safe-in-concurrentdictionary). The `AddOrUpdate` is intended for replacing the value of a key with another value, not for modifying an existing (mutable) value, and not for running arbitrary code that has side-effects. The `updateValueFactory` delegate is not invoked in a synchronized manner, and may even be invoked multiple times. – Theodor Zoulias Mar 08 '21 at 13:50

0 Answers0