C# What's up with font.DrawText
I was testing a DX scrolling banner that I've recently completed. The problem is that it's consuming very large amounts of memory.
The string to be scrolled is created using an array of characters and their sizes (using DX measure string) created from the source string (rss feed) and stored in an array. The rss feed, in this case, was about 500 characters long.
To create the scrolled string, I simply add/remove characters as the come into/outof view (using panel width & character sizes to determine the time to add/remove characters from the string) on the display panel. It works very well but is using 200M of memory. The string is never more that about 80 characters long (I've made sure of this by using an alert if it exceeds 80 chars). The amount of characters in the string is dependant, of course, on the size of the font.
If I comment out the DrawText command, the app uses little memory (proving that it's not some other part of the code). If I just scroll the entire string (500 chars) the memory used is only 32M. However, I'm now using lots of Proc scrolling such a large string.
I've noticed that when you draw a static (not scrolling) large string and then follow it with, say, a single character string, DrawText does not free the memory used to draw the large string. I'm using theString.Remove & theString.Insert to create the string to be scrolled. The memory seems to crawls up as each character is Added/Subtracted and once the entire RSS feed string has been scrolled, the memory usage stays static - at 200M - from then on in.
What's going on? Any help very much appreciated... it's driving me nuts! I could just split the feed into strings but it makes more sense to do it character by character.
private void sync()
{
if (device.RasterStatus.ScanLine)
{
UpdateDisp();
if (ArStringSegments.Count != 0)
{
for (int i = 0; i != Speed; i++)
{
# region Add a character to the displayed string
if (FirstCharLength == 0 && AddChrIndex != ArStringSegments.Count)
{
StringProps StringProps = (StringProps)ArStringSegments开发者_开发技巧[AddChrIndex];
if (ScrollDirection == Direction.ToLeft)
{
theString = theString.Insert(theString.Length, StringProps.String);
}
AddChrIndex++;
}
# endregion Add a character to the string
# region remove a character from the string as it goes beyond the veiwable area
if (RemoveChrIndex != ArStringSegments.Count)
{
if (ScrollDirection == Direction.ToLeft)
{
if(ScrollInc == 0 - LargestChar)
{
StringProps RemoveString = (StringProps)ArStringSegments[RemoveChrIndex];
theString = theString.Remove(0, 1);
ScrollInc += RemoveString.Size1;
RemoveChrIndex++;
}
}
}
# endregion remove a character from the string as it goes beyond the veiwable area
# region Increment/decrement position
if (ScrollDirection == Direction.ToLeft)
{
ScrollInc--;
FirstCharLength--;
}
# endregion Increment/decrement position
# region Entire string has gone out of viewable area, scroll out by an amount and then start again.
if ((ScrollInc == 0 - (ScrollOutLength + LargestChar ) && ScrollDirection == Direction.ToLeft) ||
(ScrollInc == PanWidth + (ScrollOutLength + LargestChar) && ScrollDirection == Direction.ToRight))
{
theString = "";
AddChrIndex = 0;
RemoveChrIndex = 0;
FirstCharLength = 0;
if (ScrollDirection == Direction.ToLeft)
{
ScrollInc = this.PanWidth;
}
else
{
ScrollInc = 0;
RightBoundary = 0;
}
}
# endregion entire string has gone out of viewable area, scroll out by an amount and then start again.
}
}
}
ScanCount = device.RasterStatus.ScanLine;
}
private void UpdateDisp()
{
try
{
if (device.CheckCooperativeLevel(out DeviceStatus))
{
if (UpdateDisplayEnabled == true)
{
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
// background image Texture
BackSprite = new Sprite(device);
BackSprite.Begin(SpriteFlags.AlphaBlend);
BackSprite.Draw2D(PanelTexture, new Point(0, 0), 0.0F, new Point(0, 0), Color.White);
BackSprite.End();
BackSprite.Dispose();
// draw the text
Draw2DText(FeedText[i], ScrollInc, 0, FontColor);
font.DrawText(null, theString, new Rectangle(ScrollInc, 0,
device.EndScene();
if (device.CheckCooperativeLevel(out DeviceStatus)) device.Present((IntPtr)DxRenderPanel);
}
}
}
We can't see your code, and so all I can give you is conjecture. With that in mind:
.Net uses garbage collection to manage memory. To make things more efficient, the garbage collector might decide it doesn't need to free memory until there's pressure from somewhere to do so. If you have a machine with several gigabytes of free ram, than there's no pressure to release it and this might be just fine.
That said, there are some things you could be doing wrong to prevent the garbage collector from release ram that it might otherwise be perfectly happy to return to your system.
- Are you holding on to reference to your string images somewhere long after you need to?
- Are you creating the images much faster than is needed?
- If the scrolling string is marquee that will cycle, could you instead cache each image in the cycle rather than draw a new one?
- Could you build one image (or two for the wrap-around) and only show the relevant portion by moving your control and hiding the edges behind something?
- Are you creating a new string object for every DrawText() call, rather than re-using them?
- Are you creating a lot of new font objects (maybe one per character) that you don't really need?
- Most of all, are you drawing into a brand new bitmap every time, or could you clear an existing bitmap and draw the new string over that?
精彩评论