|
I didn't mean thread sync in the traditional sense, but synchronization with threads as you said.
Yeah I read too much into that statement. I should have known that is what you meant.
The fact that adding items uses SendMessage is something I know well - almost everything you call on controls in Windows Forms calls SendMessage. It is for this reason - as I explained before when talking about the encapsulation of the Windows Common Controls - that you must use Control.Invoke. Believe me, I know.
To be fair I wasn't trying to educate you on the internals of the common controls in .NET but rather explain what is happening so that others that read the posts, that might not know, can have a better understanding. I've read quite a bit of your posts and you are a regular contributor to Code Project, plus you work at Microsoft. It was in no way an attempt to educate you on the internals but more of a reference for someone who doesn't know.
The performance issues all come down to the efficiency of your code. I could build a massive (around 2,000 nodes on average) tree (data-fead, polymorphic design) in just a couple of seconds from a DataSet. Adding ListViewItems to a ListView wasn't really a problem either.
The number of items I expect to add are from 1,000 - 70,000. For the cases that I need to display 70,000 and I already know ahead of time what they are I use virtual listview so that it doesn't have to create or load each item until it is displayed on the screen. But that doesn't work when showing search results in real-time.
Another thing that I will bring up is that I haven't ran a profile on the code in question yet. It is always important to profile code before making assumptions on why it is so slow.
-
Drew
|
|
|
|
|
For 70,000 you might consider a virtual list. This will be supported in .NET 2.0, which takes advantage of functionality that already exists in the List-View common control now. If you haven't downloaded 2.0 yet, you should do so (beta 1 as of this posting) and see how it works using ildasm.exe or .NET Reflector, or just read the common controls documentation and do it yourself (it's not difficult - just tedious).
This will greatly improve performance and won't how as many system resources (well, not until you load the whole thing and don't clean-up behind you - of which I'm not sure off-hand the "enhanced" ListView does (didn't look)).
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
For 70,000 you might consider a virtual list. This will be supported in .NET 2.0, which takes advantage of functionality that already exists in the List-View common control now. If you haven't downloaded 2.0 yet, you should do so (beta 1 as of this posting) and see how it works using ildasm.exe or .NET Reflector, or just read the common controls documentation
Yeah I have created a virtual listview control in .NET 1.1 It is wonderful for loading that many items but I found an issue when you want to add a single item to the list repeatably. When you set the count with the Win32 API it resets the whole list and causes a slow redraw problem again. It's what I use when I have a list of 70,000 already computed and have them available.
I will say thought that there appears to be a problem with the virtual listview on Windows 98 SE. The text of the items don't show up when using a Virtual list view. But that is a seperate problem that I had to deal with.
I have VS 2k5 Beta 1 and will definately check out how they implement the virtual list view and see if it works on Win98 SE. That would be great if it did and I could figure out what I did differently from them.
You know when VS 2k5 Beta 1 is going Gold?
-
Drew
|
|
|
|
|
Thanks Heath,
I am not sure if the data are being gathered on another thread, so I altered my code to use a delegat data formater and used the listview's Invoke method. So the code looks like this:
<br />
protected void LoadLogList()<br />
{<br />
...<br />
SqlCommand m_sqlCmd = new SqlCommand( "DF_Get_DayLog_List",<br />
MainForm.Instance.FDSConnection.DBConnection.Connection );<br />
<br />
m_sqlCmd.CommandType = CommandType.StoredProcedure;<br />
m_sqlCmd.Parameters.Add("@DF_TrafficID", iTrafID );<br />
<br />
SqlDataReader reader = m_sqlCmd.ExecuteReader();<br />
<br />
myMethodDelegate myD1 = new myMethodDelegate( this.LoadLogItem );<br />
object[] param = {reader};<br />
<br />
while( reader.Read() )<br />
{<br />
lvwLogDays.Invoke(myD1, param);<br />
}<br />
<br />
reader.Close();<br />
<br />
}<br />
<br />
public void LoadLogItem(SqlDataReader reader)<br />
{<br />
DateTime Date = reader.GetDateTime( reader.GetOrdinal( "LogDate" ) );<br />
string strTemp = Date.ToString( "MM/dd/yyyy" );<br />
OpenDayLogData DayLogData = new OpenDayLogData();<br />
<br />
ListViewItem item = lvwLogDays.Items.Add( strTemp );<br />
<br />
strTemp = reader["LogStatus"].ToString().Trim();<br />
item.SubItems.Add( strTemp );<br />
<br />
DayLogData.LogID = Convert.ToInt32(reader["DF_LogID"].ToString(), 10);<br />
DayLogData.LogDayID = Convert.ToInt32(reader["DF_LogDayID"].ToString(), 10);<br />
item.Tag = DayLogData;<br />
}<br />
I experienced no speed change. Am I being unreasonable to expect 500 lines to be loading into the list view in much less than 10 seconds (on a 2.x GHz P4 machine, lots of RAM - nothing else - much - going on)?
|
|
|
|
|
Hi,
I've been struggling with the following problem for quite some time. Google wasn't very helpfull, too...
Is there an easy way to accomplish having three (or more) panels which can be resized by a splitter? So, if you increase Panel3, Panel2 should be decreased by the same amount. This obviosly can not be done with the default splitter control, because there are more than two panels involved.
Do you have an idea how this could be done?
--------------------
|
| Panel1
|
--------------------
|
| Panel2
|
--------------------
|
| Panel3
|
--------------------
Thanks,
Dennis
|
|
|
|
|
I think you have to use 2 spliters and dock your panels as following :
------
| Panel 1 - Dock Top
-----
<----- spliter 1
-----
| Panel 2 - Dock Center (Fill)
-----
<---- spliter 2
-----
| Panel 3 - Dock Bottom
-----
I hope you understand...
By the way... visit http://nehe.gamedev.net[^]
|
|
|
|
|
I already gave that a try... it works fine for three panels. But increase that number to 5...
btw, I don't know the number of panels that will be displayed. The user can determine this at runtime.
Dennis
|
|
|
|
|
And you definitely don't want to start adding panels for each case, either. This adds a lot of overhead.
The Splitter class has both SplitterMoved and SplitterMoving events you could handle. Do handle these intelligently (i.e., writing intelligent code - not duplicating it) use the same event handler for each splitter and iterate through the splitters to change their size using the appropriate location and/or size properties:
private void resizeYoungerSiblings(object sender, EventArgs e)
{
Splitter split = sender as Splitter;
if (split != null)
{
int index = Controls.GetChildIndex(split);
if (index >-1)
{
for (int i=index; i<Controls.Count; i++)
{
Splitter sibling = Controls[i] as Splitter;
if (sibling != null)
{
}
}
}
}
} You don't have to worry about this event handler being called for resizing the other splitters since the event is only fired by mouse events (OnMouseMove calls OnSplitterMoving ).
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Thanks for your replay... still, I did not get it working.
I will try to give you a better explanation of my problem.
The panels are actually usercontrols. So I have 3 usercontrols among each other. I want to be able to change their heigth during runtime with something similar to a splitter. If one unsercontrol gets resized (e.g. heigth += 20), it affects the usercontrol next to it (in this case: height -= 20).
To be honest, I don't know where to start. Placing a splitter on the usercontrol doesn't do the trick. If you place your mouse over the splitter, it will change the Cursor to HSplit, but the events dont get fired.
I like your idea with just one event being fired by every splitter, but my problem at the moment is much more fundamental: where to place tose splitter.
Thanks for your help & time,
Dennis
|
|
|
|
|
I can't seem to think straight at the moment, so could anyone tell me why I am getting this error or how to get more information on it?
This is the error:
An unhandled exception of type 'System.Xml.XmlException' occurred in system.xml.dll
Additional information: System error.
This is the function:
private XmlDocument xd;
private XmlDocument tempdoc;
private void btnNewXML_Click(object sender, System.EventArgs e)
{
// Is a FLAPP directory selected?
if (CheckFLAPP(tboxFLAPP.Text) == true)
{
//create default xml document
tempdoc = new XmlDocument();
//load in generic document structure
tempdoc.LoadXml("<pens>" +
"<database id="" name="DATABASE">" +
"" +
"<column id="" name="PEN" min="" max="" color="" description="" aux1="" aux2="" bool1="" bool2="">" +
"" +
"<database>" +
"<pens>");
xd = new XmlDocument(); **ERROR OCCURS ON THIS LINE**
xd = tempdoc;
if(ValidateXmlDoc(xd))
{
DisplayInitXML(xd);
}
else
{
MessageBox.Show("The new xml document produced was invalid. Please contact ... for help.");
}
}
else
{
MessageBox.Show("You have not selected a FLAPP directory!");
}
}
Any help is appreciated.
alphanorm
|
|
|
|
|
Shouldn't that <table/> tag be </table>? Sometimes it helps when you pass valid XML to the LoadXML function : ).
|
|
|
|
|
OH SNAP!! Thanx fer the fresh set of eyes Brian. I think I need to sleep now.
alphanorm
|
|
|
|
|
I need to be able to display AOL .ART format files as well as the usual JPEG, GIF, etc. The VS.NET PictureBox does not support this format.
Does anyone have a suggest how this can be achieved?
Many thanks
Chris
|
|
|
|
|
Actually, GDI nor GDI+ (around which System.Drawing is built) does not natively support that format. You need a decoder that supports the .ART extension. I remember that IE a long time ago had this, but I'm not sure about it now.
If there's any hope for help, it would help to have an example. Could you post a .ART file up somewhere where I can take a look?
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Heath,
Thanks for replying to my post (again!!).
IE does indeed support AOL ART files, I played around with it some time ago (but can't find the code now!). It worked but I could only get it to work with a file as it's source. The code I have resizes images on the fly without writing out to a file - I couldn't work out how to get IE to accept anything other than a file.
Unfortunately any .art files I have are at work, and I am now at home for the weekend (Doh!). I'm scouting around the net to see if I can locate some, but putting .art into google gets the whole world back!
Chris
|
|
|
|
|
I found one in the first result with "AOL art image file". I'll need some time to take a look at how it is supported. GDI appears to support it but GDI+ doesn't "out of the box".
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Thanks for taking the time to look at this Heath.
|
|
|
|
|
Heath,
Did you ever get a chance to look at this? I put it on the 'back burner' to concentrate on other work, but have started looking at this again - any help would be appreciated, I can assure you it is in a good cause!
Chris
|
|
|
|
|
I did some originally but didn't find any answers. The best I can tell you is to go to http://lab.msdn.microsoft.com/vs2005[^] and request support for it in GDI+.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Oh well, worth a try...
Thanks for your efforts!
If anyone else has any bright ideas for displaying .art files it would be appreciated.
|
|
|
|
|
I am trying to override the WM_PAINT message and I am continuously getting WM_PAINT messages. The basic code snippet is:
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PAINT)
{
Trace.WriteLine(" WM_PAINT event");
m.Result = IntPtr.Zero;
}
else
{
base.WndProc(ref m);
}
}
As I am planning to do all the drawing I don't want to call the base message processing for the WM_PAINT messages. Any ideas?
|
|
|
|
|
your code looks fine to me, could you be more specific about your problem?
I hope you understand...
By the way... visit http://nehe.gamedev.net[^]
|
|
|
|
|
I probablly should have mentioned that this is for a toolbar control that only contains buttons.. It seems that when I call the base message processing I only get the one WM_PAINT message (for instance when the cursor is dragged over a button). If I don't call the base message processing I constantly get WM_PAINT messages.
|
|
|
|
|
WM_PAINT methods are handled differently than other messages by Windows. A WM_PAINT message is automatically sent if there are any outstanding invalid regions in your window. Windows knows that have painted your window, and thus stop sending WM_PAINT, after an application calls the Win32 functions BeginPaint\EndPaint. The easiest way to accomplish this in your case is by calling the base class OnPaint, which handles it for you.
|
|
|
|
|
WM_PAINT is sent for many reasons, and the best way to optimize your code is to honor the PaintEventArgs.ClipBounds property passed to OnPaint . Only draw what's necessary.
Overriding WndProc to handle painting is almost never the right way to handle user painting. Instead, you call SetStyle in the constructor and override OnPaint like so:
public MyControl()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint,
true);
}
protected override void OnPaint(PaintEventArgs e)
{
} Control.WndProc already handles the WM_PAINT messages and wraps the arguments necessary for painting in the PaintEventArgs and disposes the Graphics object when OnPaint returns.
If you want double-buffering for your custom drawing code, also OR the ControlStyles.DoubleBuffer enumeration with SetStyle in the example source above.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|