Stopwatch sw = new Stopwatch();
sw.Start();
for (Int32 i = 0; i < 1000000; i++)
textBox_UserName.Text = String.Empty;
sw.Stop();
Int64 elapsed_StringEmpty = sw.ElapsedMilliseconds;
sw.Reset();
sw.Start();
for (Int32 i = 0; i < 1000000; i++)
textBox_UserName.Clear();
sw.Stop();
Int64 elapsed_Clear = sw.ElapsedMilliseconds;
The two tests produced very different results:
sw.Reset();
sw.Start();
textBox_UserName.BeginChange();
for (Int32 i = 0; i < 1000000; i++)
textBox_UserName.Clear();
textBox_UserName.EndChange();
sw.Stop();
Int64 elapsed_Clear_Change = sw.ElapsedMilliseconds;
In fact the same operation took now
6030 ms. It is still far from than the String.Empty assignment, but just a bit more than half the time of the previous execution.
/// <summary>
/// Clear all the content in the TextBox control.
/// </summary>
public void Clear()
{
using (this.TextSelectionInternal.DeclareChangeBlock())
{
this.TextContainer.DeleteContentInternal((TextPointer)this.TextContainer.Start, (TextPointer)this.TextContainer.End);
TextSelectionInternal.Select(this.TextContainer.Start, this.TextContainer.Start);
}
}
This code declares a "ChangeBlock" and then deletes the content. A ChangeBlock is defined as:
private class ChangeBlock : IDisposable
{
internal ChangeBlock(ITextRange range, bool disableScroll)
{
_range = range;
_disableScroll = disableScroll;
_range.BeginChange();
}
void IDisposable.Dispose()
{
_range.EndChange(_disableScroll, false /* skipEvents */);
GC.SuppressFinalize(this);
}
private readonly ITextRange _range;
private readonly bool _disableScroll;
}
// DeleteContent worker. Removes content from the tree.
internal void DeleteContentInternal(TextPointer startPosition, TextPointer endPosition)
{
TextTreeNode containingNode;
int symbolCount;
int charCount;
TextTreeUndoUnit undoUnit;
TextPointer deletePosition;
startPosition.SyncToTreeGeneration();
endPosition.SyncToTreeGeneration();
if (startPosition.CompareTo(endPosition) == 0)
return;
BeforeAddChange();
undoUnit = TextTreeUndo.CreateDeleteContentUndoUnit(this, startPosition, endPosition);
containingNode = startPosition.GetScopingNode();
// Invalidate any TextElementCollection that depends on the parent.
// Make sure we do that before raising any public events.
TextElementCollectionHelper.MarkDirty(containingNode.GetLogicalTreeNode());
int nextIMEVisibleNodeCharDelta = 0;
TextTreeTextElementNode nextIMEVisibleNode = GetNextIMEVisibleNode(startPosition, endPosition);
if (nextIMEVisibleNode != null)
{
// The node following the delete just became the first sibling.
// This might affect its ime char count.
nextIMEVisibleNodeCharDelta = -nextIMEVisibleNode.IMELeftEdgeCharCount;
nextIMEVisibleNode.IMECharCount += nextIMEVisibleNodeCharDelta;
}
// First cut: remove all top-level TextElements and their chilren.
// We need to put each TextElement in its own tree, so that any outside
// references can still play with the TextElements safely.
symbolCount = CutTopLevelLogicalNodes(containingNode, startPosition, endPosition, out charCount);
// Cut what's left.
int remainingCharCount;
symbolCount += DeleteContentFromSiblingTree(containingNode, startPosition, endPosition, nextIMEVisibleNodeCharDelta != 0, out remainingCharCount);
charCount += remainingCharCount;
Invariant.Assert(symbolCount > 0);
if (undoUnit != null)
{
undoUnit.SetTreeHashCode();
}
// Public tree event.
deletePosition = new TextPointer(startPosition, LogicalDirection.Forward);
AddChange(deletePosition, symbolCount, charCount, PrecursorTextChangeType.ContentRemoved);
if (nextIMEVisibleNodeCharDelta != 0)
{
RaiseEventForNewFirstIMEVisibleNode(nextIMEVisibleNode);
}
}
This is the core of the method and lets us understand why it is taking so much time.
DependencyProperty dp = System.Windows.Controls.TextBox.TextProperty;
sw.Reset();
sw.Start();
for (Int32 i = 0; i < 1000000; i++)
textBox_UserName.ClearValue(dp);
sw.Stop();
Int64 elapsed_ClearValue = sw.ElapsedMilliseconds;
sw.Reset();
sw.Start();
for (Int32 i = 0; i < 1000000; i++)
textBox_UserName.SetValue(dp, null);
sw.Stop();
Int64 elapsed_SetValue = sw.ElapsedMilliseconds;
The ClearValue method took
448 ms to execute 1 million times, while the SetValue method took
393 ms: closer to, but still about 1.5 times slower than the simple textBox_UserName.Text = String.Empty assignment.
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (4)
Commented:
Thanks for writing it - voted Yes.
Author
Commented:Thank you!
Commented:
You have a nice way of presenting technical information in an easily read format.
"Yes" vote above.
Author
Commented: