I'm building a C# Gui. Included in it is a Refresh event which gets called every second or so to refresh the screen.
private void RefreshEverySecond_Tick(object o, EventArgs a)
{
if (Condition1)
{
QuickStatusTextBox.Text = "Condition 1";
QuickStatusTextBox.Font = new Font(QuickStatusTextBox.Font, FontStyle.Bold);
}
else
{
QuickStatusTextBox.Text = "Condition 2";
QuickStatusTextBox.Font = new Font(QuickStatusTextBox.Font, FontStyle.Regular);
}
}
In researching the way to do this, I've seen answers like this which encourage this behavior:
Easiest way to change font and font size with visual C#
BUT I've also seen a lot of chatter saying I should be using "Using" for IDisposable objects which I gather Font is.
When should I use "using" blocks in C#?
And examples of using with fonts:
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Question: What is the right way to change a text box from Bold to Regular at periodic intervals? Does my method violate any rules or risk a memory leak or contention because I'm not using "using", and is there a "proper" way using Using? Remember this updates every second... so I'm likely keeping the Garbage collector busy but what other side effects are going to bite me?
A Font object in Winforms .NET actually encapsulates two things: a description of a typeface, and a handle to a GDI object which represents that typeface. One of those things represents a limited resource (the GDI handle) and the other does not.
While it might have been possible to have controls use the GDI handles of fonts which are used to set their properties, built-in controls do not do so. Instead, the line myControl.Font = myFont; will cause myControl to capture a description of the typeface encapsulated by myFont and make its own Font object for internal use. The control will ensure that its internal-use Font object gets disposed when either the control is disposed or its myControl.Font is set to a different font, but the control will neither dispose myFont nor care about when or whether it is disposed. Interestingly, it won't care if myFont had been disposed even before the statement above executed. Assuming nothing else has written it, reading myControl.Font will return a reference to myFont rather than the control's internal font object; if myFont has been disposed, then myControl.Font will return a reference to a font object which has been disposed (but could still be used to set other controls' Font properties).
If one wishes to most accurately ensure the prompt cleanup of GDI font resources, any font objects which will be used only as "templates" and won't be used for actual drawing may be disposed as soon as they are created. I don't know whether that should be recommended as a pattern, since I can't find any official documentation of controls' Font behavior, but it seems wasteful to have font objects holding GDI resources that are never going to be used. It's too bad controls' Font property doesn't use some sort of documented FontDescription class which would encapsulate just the typeface description but not the GDI handle, since such a design would make things a lot clearer.
Related
I am an old delphi programmer, I am used to creating objects and using them entire time for efficient memory usage. But in c# (maybe all the tutorials I've ever seen), you are creating stuffs with new every time (thanks to garbage collector!!, let me do the coding)..
Anyway, I am trying to create a designing software which has lots of drawing.
My question is: do I have to create a graphics object, or use the protected override void OnPaint(PaintEventArgs e) e.Graphics every painting event.. because when I create a graphic object and then resize the control that I draw on, the graphic object that I created, has that clipping problem and only draws old rectangle region..
thanks
Caching objects makes sense when the object is expensive to create, cheap to store and relatively simple to keep updated. A Graphics object is unique in that none of these conditions are true:
It is very cheap to create, takes well less than a microsecond.
It is very expensive to store, the underlying device context is stored in the desktop heap of a session. The number of objects that can be stored is small, no more than 65535. All programs that run in the session share that heap.
It is very hard to keep updated, things happen behind your back that invalidates the device context. Like the user or your program changing the window size, invalidating the Graphics.ClipBounds property. You are wasting the opportunity to use the correct Graphics object, the one passed to you in a Paint event handler. Particularly a bug factory when you use double-buffering.
Caching a Graphics object is a bug.
If you want to draw on the surface always use the Graphics object from the Paint event!
If you want to draw into a Bitmap you create a Graphics object and use it as long as you want.
For the Paint event to work you need to collect all drawing in a List of graphic actions; so you will want to make a nice class to store all parameters needed.
In your case you may want to consider a mixed approach: Old graphic actions draw into a bitmap, which is the e.g. BackgroundImage or Image of your control
Current/ongoing drawing are done on the surface. This amounts to using the bitmap as a cache, so you don't have to redraw lots of actions on every little change etc
This is closely related to your undo/redo implementation. You could set a limit and draw those before into a Btimap and those after onto the surface..
PS: You also should rethink your GC attitude. It is simple, efficient and a blessing to have around. (And, yes, I have done my share of TP&Delphi, way back when they were affordable..) - Yes, we do the coding, but GC is not about coding but about house keeping. Boring at best.. (And you can always design to avoid it, but not with a Graphics object in a windows system.)
A general rule for every class that implements IDisposable is to Dispose() it, as soon as possible. Make sure you know about the using(...){} statement.
For drawing in WinForms (GDI+) the best practice is indeed to use the Graphics object from PaintEventArgs. And because you didn't create that one, do not Dispose() it. Don't stash it either.
I have to completely disagree with other more experienced members here who say it's no big deal or in fact better to recreate the Graphics object over and over.
The HDC is a pointer to a HDC__ struct, which is a struct with one member, "int unused". It's an absolute waste and stupidity to create another instance/object every time drawing needs to be done. The HDC is NOT large, it's either 4 or 8 bytes, and the struct it points to is in nearly all cases 4 bytes. Furthermore, on the point that one person made, it doesn't help that the graphics object be made with the "static" keyword at the beginning of the WndProc() before the switch, because the only way to give the Graphics object a device context or handle to paint on is by calling its constructor, so "static" does nothing to save you from creating it over and over again.
On top of that Microsoft recommends that you create a HDC pointer and assign it to the same value PAINTSTRUCT already has, every, single WM_PAINT message it sends.
I'm sorry but the WinAPI in my opinion is very bad. Just as an example, I spent all day researching how to make a child WS_EX_LAYERED window, to find out that in order to enable Win 8 features one has to add code in XML with the OS's ID number to the manifest. Just ridiculous.
We're dealing with the GC being too quick in a .Net program.
Because we use a class with native resources and we do not call GC.KeepAlive(), the GC collects the object before the Native access ends. As a result the program crashes.
We have exactly the problem as described here:
Does the .NET garbage collector perform predictive analysis of code?
Like so:
{ var img = new ImageWithNativePtr();
IntPtr p = img.GetData();
// DANGER!
ProcessData(p);
}
The point is: The JIT generates information that shows the GC that img is not used at the point when GetData() runs. If a GC-Thread comes at the right time, it collects img and the program crashes. One can solve this by appending GC.KeepAlive(img);
Unfortunately there is already too much code written (at too many places) to rectify the issue easily.
Therefore: Is there for example an Attribute (i.e. for ImageWithNativePtr) to make the JIT behave like in a Debug build? In a Debug build, the variable img will remain valid until the end of the scope ( } ), while in Release it looses validity at the comment DANGER.
To the best of my knowledge there is no way to control jitter's behavior based on what types a method references. You might be able to attribute the method itself, but that won't fill your order. This being so, you should bite the bullet and rewrite the code. GC.KeepAlive is one option. Another is to make GetData return a safe handle which will contain a reference to the object, and have ProcessData accept the handle instead of IntPtr — that's good practice anyway. GC will then keep the safe handle around until the method returns. If most of your code has var instead of IntPtr as in your code fragment, you might even get away without modifying each method.
You have a few options.
(Requires work, more correct) - Implement IDisposable on your ImageWithNativePtr class as it compiles down to try { ... } finally { object.Dispose() }, which will keep the object alive provided you update your code with usings. You can ease the pain of doing this by installing something like CodeRush (even the free Xpress supports this) - which supports creating using blocks.
(Easier, not correct, more complicated build) - Use Post Sharp or Mono.Cecil and create your own attribute. Typically this attribute would cause GC.KeepAlive() to be inserted into these methods.
The CLR has nothing built in for this functionality.
I believe you can emulate what you want with a container that implements IDispose, and a using statement. The using statement allows for defining the scope and you can place anything you want in it that needs to be alive over that scope. This can be a helpful mechanism if you have no control over the implementation of ImageWithNativePtr.
The container of things to dispose is a useful idiom. Particularly when you really should be disposing of something ... which is probably the case with an image.
using(var keepAliveContainer = new KeepAliveContainer())
{
var img = new ImageWithNativePtr();
keepAliveContainer.Add(img);
IntPtr p = img.GetData();
ProcessData(p);
// anything added to the container is still referenced here.
}
Refactoring some code again. Seeing some of this in one of the ASP.NET pages:
using (TextBox txtBox = e.Row.Cells[1].FindControl("txtBox") as TextBox)
{
}
There is no need to dispose txtBox, because it's just a reference to an existing control. And you don't want the control disposed at all. I'm not even sure this isn't harmful - like it would appear to ask for the underlying control to be disposed inappropriately (although I have not yet seen any ill effects from it being used this way).
TextBox inherits its implementation of IDisposable from its Component superclass. That implementation removes the component from its site container if it has one.
So, doing that might have nefarious effects if the text box actually resides in a site container. Also, after calling Dispose() on an object, you should not use it again, no matter what (it's not in a usable state anymore).
I'd suggest you avoid that pattern with ASP.NET web controls.
This is wrong, it shouldnt be used like this. I would imagine there are potential problems using this that wont show up immediately. The textboxes dispose is called upon leaving the using statement but it wont be garbage collected immediately. If it is collected then you will have problems later when you try to access that control.
The TextBox instance could potentially be null if not found, so Dispose() is called a NullReferenceException would be thrown.
I've never seen that pattern in practice, but if you need to use it, it'd be worth handling any potential errors.
There should be no negative secondary effects, but it's not necessary either. If we did using (x) { ... } on everything that implements IDisposable in the CLR most C# code would be unreadable.
Actually, here the TextBox instance is accessible only to the context inside the brackets of using statement, maybe that was the main reason of using it.
From MSDN:
Within the using block, the object
is read-only and cannot be modified
or reassigned.
So I guess you can only read the textbox properties, but not change them, inside the using block.
I wrote a custom control in C# that inherits from the RichTextBox. The purpose of this control is to contain all improvements and changes, such as modified line numbering and having the control repaint itself only when it should.
Yesterday, I noticed memory spikes (and often, OOM exceptions) when accessing the Lines property of this control (there are 600,000+ lines in the control at times). I coded workarounds that no longer involve it, but I would still like to completely remove it so people who use my control in the future do not use it.
The Lines property is System.Windows.Forms.TextBoxBase.Lines. Ideally, I'd like the string[] for this property to never be touched; when I load text in the control, I do NOT want the control to do anything to fill this lines property (because it's completely pointless and is consuming some time and resources).
Anyone have any ideas?
EDIT: I tried
public override string[] Lines
{
get { return null; }
set { ; } // do nothing
}
But VS says "cannot override inherited member System.Windows.Forms.TextBoxBase.Lines.get because it is not marked virtual, abstract, or override.
So it looks like I can't override or remove it. I think the RichTextBox is setting the property because it is filled after change the text. Is there a way for me to capture and handle that message?
Hmya, it is only going to slow down a decent programmer for no more than 5 minutes:
string[] lines = ((RichTextBox)myEditor1).Lines;
which will blow just as hard. There isn't much point in trying to prevent usage of your class that can be used anyway. The Lines property ought to be useful to anybody that uses your editor, it covers the very basic need to be able to retrieve the text that was edited. Don't throw out the baby with the bath water.
The real problem here is that RTB uses so much unmanaged memory to store the text, leaving little left for the garbage collected heap. It gets really slow too once you pump thousands of lines into it. No component should ever be allowed to swallow up half of all available memory. Either limit the number of lines you allow to edit or use a better editor, like ScintillaNET.
It is also rather important to be a pragmatic programmer. Beyond hiding a property needlessly. 600,000 lines in a text box is an enormous number. There a 3/4 million words in the Bible, you are displaying 6 copies of the Bible in your text box. No sane human is ever going to read that, they'll just dislike your program intensely. Not just because it is impossible to use effectively but also because it is a crash bucket.
Have you tried to shadow the property?
public new string[] Lines
{
get { throw new Exception("Not supported"); }
set { throw new Exception("Not supported"); }
}
I am having a few memory problems with a long running application; I have been inspecting the paint methods to insure that brushes are properly disposed. In the case where the Brush is created in the argument to the function, will the brush be disposed after the call?
The case is outlined below:
g.DrawString(valueText, Font, new SolidBrush(Color.Red),
I am not entirely certain, but I don't believe it is. This would be safer:
using(var redBrush = new SolidBrush(Color.Red)
{
g.DrawString(valueText, Font, redBrush);
}
No, you should do it manually. Do however examine the classes Brushes and SystemBrushes, for ready-made brushes that you can use without creating new ones (and that you also don't need to / should not dispose).