Should I use some lock object on OnRender() and in OnMarketDepth() methods to solve this issue? Or something else?
Announcement
Collapse
Looking for a User App or Add-On built by the NinjaTrader community?
Visit NinjaTrader EcoSystem and our free User App Share!
Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less
Partner 728x90
Collapse
NinjaTrader
NT8 D2D error
Collapse
X
-
Hello,
Thank you for the question.
This is likely not related to needing a lock, this is a D2D error or part of the rendering system.
This could potentially be caused by code you are using in the case it causes the render to fail, or this could have come from some action.
Can you tell me, does this occur while using specific syntax? if so could you provide a sample that shows the error for me to review?
I look forward to being of further assistance.JesseNinjaTrader Customer Service
-
My typical draw code is like this. indicator var is my NT8 custom indicator instance.
Code:public void Draw(ChartControl chartControl, ChartScale chartScale) { float best_x = X + OUTER_MARGIN, trade_x; float y0 = 0, y1 = 0; // Best Ask float h = Helper.GetRowYsHeight( chartScale, indicator.TickSize, lastAskPrice, ref y0, ref y1); RectangleF bounds = new RectangleF(best_x, y0, BEST_BIDASK_WIDTH, h); indicator.RenderTarget.DrawText(BestAskVolume.ToString(), tfVolume, bounds, indicator.AskBrush.ToDxBrush(indicator.RenderTarget)); // Offer traded volume if (AskVolume > 0) { trade_x = best_x + BEST_BIDASK_WIDTH + INNER_MARGIN; bounds = new RectangleF(trade_x, y0, TRADE_WIDTH, h); indicator.RenderTarget.FillRectangle(bounds, indicator.AskBrush.ToDxBrush(indicator.RenderTarget)); indicator.RenderTarget.DrawText(AskVolume.ToString(), tfVolume, bounds, indicator.TapeSnapshotAskVolumeBrush.ToDxBrush(indicator.RenderTarget)); } // Best Bid h = Helper.GetRowYsHeight(chartScale, indicator.TickSize, lastBidPrice, ref y0, ref y1); bounds = new RectangleF(best_x, y0, BEST_BIDASK_WIDTH, h); indicator.RenderTarget.DrawText(BestBidVolume.ToString(), tfVolume, bounds, indicator.BidBrush.ToDxBrush(indicator.RenderTarget)); // Bid traded volume if (BidVolume > 0) { trade_x = best_x + BEST_BIDASK_WIDTH + INNER_MARGIN; bounds = new RectangleF(trade_x, y0, TRADE_WIDTH, h); indicator.RenderTarget.FillRectangle(bounds, indicator.BidBrush.ToDxBrush(indicator.RenderTarget)); indicator.RenderTarget.DrawText(BidVolume.ToString(), tfVolume, bounds, indicator.TapeSnapshotBidVolumeBrush.ToDxBrush(indicator.RenderTarget)); } }
Comment
-
Hello,
Have you determined this code specifically controls the error? What i mean is that if you comment out this code would the error still occur or does this specifically control it?
I am unable to compile the sample provided to test if this does cause an error or not, in the case this is the specific syntax controlling the error I would like to ask for a sample I could compile and test.
I look forward to being of further assistance.JesseNinjaTrader Customer Service
Comment
-
It makes no sense because of error occurred only sometimes, 1 from 10 run I think. And I have no idea what class from 5-6 plotted classes makes issue.
As I have learned from this https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
exeption might occurred after thread tries to get write lock for some resource.
E.g. changing TextFormatLayout object instance after it was created and shared with others threads. Am I right?
Btw, can OnRender() method be called from different threads by NT core, waiting for timeout and throwing lock exeption on time expired?
What does this code? Should I dispose DxBrush after using or it will be disposed by D2D library? If not, next time I call ToDxBrush() will it look for brush in D2D global or app cache? Now it's unclear for me.
Code:Brush.ToDxBrush(RenderTarget)
Last edited by ren37; 06-09-2016, 04:22 PM.
Comment
-
Hello,
Thank you for the reply.
I would be unsure if what you are experiencing would be related to the MSDN article, the sharpDX render errors can come from many items in the platform as the platform uses SharpDX for rending most types of items.
Again it would be hard to say depending on what has been provided if that is related or not, have you noted if you do not use the custom code, do you receive the same error when completing any specific actions?
If this is only being caused while using the custom code, there is a good likelihood some portion of that logic is the cause, otherwise if this can be reproduced in other ways I would like to know the steps used.
Regarding the OnRender being accessed from multiple threads, this is a question I could not answer with accuracy as I am unaware of the total process going on internally surrounding OnRender. Generally speaking the NinjaScript item you are using would only be in one thread and all items it uses would be in the associated thread.
Regarding disposing resources, in general you will need to dispose resources you create that you no longer need. This is not specific to NinjaTrader but specific to C# in general. In the case of brushes, you could dispose of a brush by calling its Dispose method.
In most cases it is best to do creation and disposal of objects in the OnRenderTargetChanged override. We have an example that applies to this question here: http://ninjatrader.com/support/helpG...rTargetChanged
I look forward to being of further assistance.JesseNinjaTrader Customer Service
Comment
-
I am glad that I am not alone in getting this D2D error. I get this error from the following actions using a custom indicator.
1. The custom indicator draws 4 rows of rectangles at the bottom of the price chart, using RenderTarget.FillRectangle() and SharpDX.Direct2D1.LinearGradientBrush, which is created and disposed for each rectangle. This is necessary as the color of each rectangle is different.
2. To avoid memory leak, the code is wrapped with using(SharpDX.Direct2D1.LinearGradientBrush LinGradBrush = GetLinGradBrush(rectf, Color0, 0f, Color1, fPos1, Color2, 1f)) {} and both the LinearGradientBrush and GradientStopCollection are disposed() accordingly.
3. Under normal condition, using a chart about 10 tabs, there is no noticeable error message.
4. When the Kinetick connection is activated, this error would start to happen, although not too often. However, if the Kinetick connection is activated and de-activated many times, this error would occur more often, causing NinjaTrader to freeze. The only way to terminate is using the Task Manager.
5. When the RenderTarget.FillRectangle() is replaced with a SharpDX geometry code, the D2D error would be less frequent but it did not solve the problem.
6. The next thing to try is to reuse the LinearGradientBrush, instead of creating and disposing for each rectangle. If any one could provide coding to reuse the LinearGradientBrush, or to resolve this D2D error, it would be greatly appreciated.
Comment
-
kkc2015,
In my custom indicator I have never seen this D2D error after reusing DX brushes.
But some dynamicaly calculated DX brushes still created and disposed inside OnRender() call.
PHP Code:[Browsable(false)] [XmlIgnore] public SharpDX.Direct2D1.Brush AskBrushDx { get; protected set; }
...
public override void OnRenderTargetChanged()
{
DisposeUnmanagedGraphics();
AskBrushDx = AskBrush.ToDxBrush(RenderTarget);
...
}
private void DisposeUnmanagedGraphics()
{
if (AskBrushDx != null) AskBrushDx.Dispose();
...
}
protected override void OnStateChange()
{
...
else if (State == State.Terminated)
{
DisposeUnmanagedGraphics();
...
}
}
Comment
-
I also had exceptions when re-using global brushes.
The problem was solved using local variables with using blocks.
Code:protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { ... using (SharpDX.Direct2D1.Brush myBrush = new SolidColorBrush( Colors.Blue ).ToDxBrush( RenderTarget )) { // painting }
Last edited by cls71; 06-17-2016, 02:21 AM.
Comment
-
Originally posted by cls71 View PostI also had exceptions when re-using global brushes.
The problem was solved using local variables with using blocks.
Code:protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { ... using (SharpDX.Direct2D1.Brush myBrush = new SolidColorBrush( Colors.Blue ).ToDxBrush( RenderTarget )) { // painting }
Comment
-
Thank you for the suggestions, ren37 and cls71.
Except for the LinearGradientBrush, all DX brushes are cloned and frozen inside (State == State.Historical) and disposed of inside OnRenderTargetChanged(), as per sample reuseablebrushes.zip provided by NinjaTrader.
As commented on my previous item 2, to avoid memory leak, the LinearGradientBrush was wrapped with the "using statement block" because I do not know how to reuse it. I was hoping that if the LinearGradientBrush were to be reused, it may solve the problem. Do you have any ideas how this can be achieved?
By the way, if many lines were drawn using the following codes, the same D2D error would occur occasionally with multi-tab chart and activation cycling of the Kineticks connection.
SharpDX.Direct2D1.StrokeStyle strokeStyle = new Stroke(Brushes.Gray, DashStyleHelper.DashDotDot, 1f).StrokeStyle;
RenderTarget.DrawLine(P1.ToVector2(), P2.ToVector2(), upLineBrushDx, 1f, strokeStyle);
The error would be resolved if strokeStyle is not passed to the DrawLine() function. Any help on this would also be appreciated.
Comment
-
Originally posted by kkc2015 View PostThank you for the suggestions, ren37 and cls71.
Except for the LinearGradientBrush, all DX brushes are cloned and frozen inside (State == State.Historical) and disposed of inside OnRenderTargetChanged(), as per sample reuseablebrushes.zip provided by NinjaTrader.
As commented on my previous item 2, to avoid memory leak, the LinearGradientBrush was wrapped with the "using statement block" because I do not know how to reuse it. I was hoping that if the LinearGradientBrush were to be reused, it may solve the problem. Do you have any ideas how this can be achieved?
By the way, if many lines were drawn using the following codes, the same D2D error would occur occasionally with multi-tab chart and activation cycling of the Kineticks connection.
SharpDX.Direct2D1.StrokeStyle strokeStyle = new Stroke(Brushes.Gray, DashStyleHelper.DashDotDot, 1f).StrokeStyle;
RenderTarget.DrawLine(P1.ToVector2(), P2.ToVector2(), upLineBrushDx, 1f, strokeStyle);
The error would be resolved if strokeStyle is not passed to the DrawLine() function. Any help on this would also be appreciated.
Have you seen my example about reusing brushes?
http://ninjatrader.com/support/forum...83&postcount=9
As what about your 2nd question see code below.
PHP Code:
[Display(Name = "Line", Order = 2, GroupName = "8. Price line")]
public Stroke PriceLineStroke
{ get; set; }
private SharpDX.Direct2D1.Brush PriceLineBrushDx;
public override void OnRenderTargetChanged()
{
if (PriceLineBrushDx != null) { PriceLineBrushDx.Dispose(); PriceLineBrushDx = null; }
PriceLineBrushDx = PriceLineStroke.Brush.ToDxBrush(RenderTarget);
}
protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
{
if (ChartBars != null)
{
RenderTarget.DrawLine(new Vector2(x, y0 + h / 2), new Vector2(chartControl.CanvasRight, y0 + h / 2),
PriceLineBrushDx, PriceLineStroke.Width, PriceLineStroke.StrokeStyle);
...
}
}
Comment
Latest Posts
Collapse
Topics | Statistics | Last Post | ||
---|---|---|---|---|
Started by ageeholdings, 05-01-2024, 05:22 AM
|
6 responses
42 views
0 likes
|
Last Post
by ageeholdings
Today, 08:37 PM
|
||
Started by tony_28217, Today, 07:04 PM
|
0 responses
8 views
0 likes
|
Last Post
by tony_28217
Today, 07:04 PM
|
||
Started by flybuzz, Today, 10:33 AM
|
1 response
9 views
0 likes
|
Last Post
by flybuzz
Today, 06:59 PM
|
||
Started by spencerp92, 10-10-2023, 09:56 AM
|
4 responses
308 views
0 likes
|
Last Post
by flybuzz
Today, 06:45 PM
|
||
Started by samish18, Yesterday, 10:13 AM
|
1 response
26 views
0 likes
|
Last Post Today, 06:15 PM |
Comment