|
so it is NOT a MouseClick issue, it is a "do many things while mouse is down" problem.
Not sure what the picture should tell me. All I see is a couple of images, some very similar or identical.
Some thoughts:
1.
While the mouse is down (I assume inside a MouseMove handler), maybe you are repeating a lot of calculations over and over, which only need to happen once, and could be moved to the actual MouseDown handler.
2.
Using multiple threads may cause delays; it all depends on how you organize things. If you have more threads than cores, and all of them are "ready" meaning they have some non-blocking job, they will be switched in and out based on the time slice which probably is 1 or 2 system ticks (that would be 10 to 30 milliseconds), a fairness principle.
3.
Watch your CPU load; if Task Manager never comes close to 100%, then more threads might help. If you are close to 100%, then many things are possible:
a. you are performing unnecessary operations (e.g. repainting an image that hasn't changed at all)
b. you have polling loops; that is the perfect way to waste CPU power
c. you have small jobs (less than 0.1 millisecond); thread switching becomes dominant cost
d. your implementation is OK, maybe the job is big, or your concept is flawed.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
The pictures in blue are the subsections I was talking about. These are extracts from the picture at the left of them. So by drawing a line on one of the blue pictures, a line is drawn in the same physical place on the yellow picture, just more precise. The other yellow pictures are just other independant pictures, which in turn can also have subsections. I already considered the MouseMove issue, but I programmed my control not to react when threads are still running. The threads I mentioned only move the viewports. Between mouseclicks. So that shouldn't be a problem. Calculations are only run when the mouse is released. I don't even use MouseMove and I watch the use of OnPaint very carefully My CPU isn't doing any overtime either. around 10% mostly, spikes of 50% (Both cores that is)
I really appreciate the effort you put in my problem though, so thanks
|
|
|
|
|
You're welcome.
I have three points for you:
1.
While several people, myself included, offered answers to your original question, I feel you still have problems, though I don't know what your problem is. If you want help, provide a context description (that you have), a specific scenario (a simple one is best), and its symptoms, emphasizing where it deviates from what you expect.
2.
and please explain "degrades". is it quality? or what? try to be precise, it improves your chances for getting useful suggestions.
3.
One more thing: I strongly suggest you read this little article of mine[^] and tell me which of the rules mentioned there you are violating, if any.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
The problem is persistent, it does not appear at specific times or actions nor series of actions. When clicking (MouseUp) one of the viewports, I have to keep my mousebutton down for a small time. In other words; My mouseclicks are not always recognized, or so it seems. This bug does not happen when I hold down the mousebutton for a small time and then release it, instead of a short click. Other than that, all is working perfectly. But it is very annoying to have to click several times or wait, to get a response from the control. This covers point 1 and 2 of your inquiry i guess. I read the article and I can proudly say that my animation is made by the rules Except the use of brushes, could that be it?
|
|
|
|
|
OK. Now we are getting tangible information. I think one of your mouse handlers is taking too long for comfort. You should not have anything blocking in there, such as Thread.Sleep; Thread.Join; and many more.
This is what I recommend to improve observability:
- add logging to all mouse event handlers; say one log on entry, one log on exit.
- make a single log method to do the actual logging, it should take a single string parameter identifying which method is calling it
- make sure the log will include a timestamp, up to the millisecond (*);
- log to one or several outputs, including a file so you have a chronological log.
Here is an example that I use often; it is based on a free running stopwatch (DateTime.Now isn't accurate enough as I explained here[^]):
public static void log(string s) {
long msec=myStopWatch.ElapsedMilliseconds;
int TID=Thread.GetCurrentThread().ManagedThreadId;
s=msec.ToString("D8")+" ["+TID.ToString("X2")+"] "+s;
Console.WriteLine(s);
File.AppendText(logFilePath, s+Environment.NewLine);
}
public void MouseDown(...) {
log("MouseDown begin");
...
log("MouseDown end");
}
If you don't touch GUI Controls in the log method, you can call it also from any thread you like to track. If it needs GUI access, you need Invoke stuff as explained here[^], but I guess you know all that.
Now run and watch the log it generates. Look for handlers taking more than 20 milliseconds; and for strange sequences of events.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
I'll try that log first thing tomorrow. My Belgian clock says it's almost 10pm, so I'm calling it a day
About the threads in MouseEvents... I fixed that already. Putting a sleep or join there would indeed slow everything down. So I am using a firing Thread which in turn calls the actual worker, so the main thread can continue without having to wait. The worker thread does have a join, but main is not affected by it. The firing thread and workers can be killed by setting a single boolean when necessary, but this does not occur. Just safety with a timeout. But like I said, I will use the log tomorrow and let you know asap. Good night
|
|
|
|
|
Not sure what I should expect with firing threads and worker threads and the like; sooner or later you have to synchronize, unless you applied a self-synchronizing data scheme, which is quite tricky and vulnerable to occasional mishaps. Even more reason to incorporate good logging...
See you.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Got it! I included an invalidate in the MouseMove event. This is necessary to draw a rectangle when dragging the mouse, but I put in the wrong conditions. This way it also fires when I am not drawing any rectangles, but just move the mouse. I hope this will solve my problem, but I am confident it will Thank you very much guys.
|
|
|
|
|
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Nope... That wasn't it, but I know were to look now...
I added a simple Console.WriteLine in my MouseUp event. Seems that this always fires when I click a viewport. But it looks AS IF it is not acknowledged. The viewport does not invalidate. So there has to be a certain timing-issue which prevents it from updating the control... I'll let you know when I find it.
|
|
|
|
|
Oooowwww... I made a deadly mistake and found the following.
I logged the use of my Morph-threads. These are assigned to a viewport to animate it's movement. So when I have four ports, four threads are launched, each controlling the movement of it's port. When I add pictures to my control by applying a Set (this is another class to interact with a database, but that's not important), every picture in this Set is added by a function AddViewport. This function also updates the control to adjust it's viewmode. Thus reorganising the pictures. But it does this every time a picture is added. So in my example 4 times. I noticed in the log that ten threads were running. And that makes sense! Because when the first picture is added, it will be the only one, so one thread is launched. Next time it will launch two. And so on. And since 1+2+3+4=10. This is perfectly logical. I should have noticed this before... Since my viewports seemed to juggle around when adding them. This is explained by the multiple threads moving the same port. Chances are that this injects dead threads and causes my control to stop responding, since I monitor the number of threads and while this is not zero, the input is blocked. Thanks Luc Pattyn, I would never have found this without your idea about the log.
|
|
|
|
|
hey
Dim picdata As PictureBox
For x = 0 To Panel1.Controls.Count - 1
picdata = Panel1.Controls.Item(x)
next
how can i do this in c#
t'hanks
|
|
|
|
|
Do you want to convert it to C#?
PictureBox picdata = new PictureBox();
for (x = 0; x <= Panel1.Controls.Count - 1; x++)
{
picdata = Panel1.Controls.Item(x);
}
You can convert your code online using this link: Convert vb.net to C#[^]
..Go Green..
|
|
|
|
|
sorry Ankur
this was to easy i tried this and variants until 4AM nothing works this way.
i don't get the Items from the controls this way;
thanks for the message anyway i have used the link you give, it go's faster this way for 70%
|
|
|
|
|
Ankur is correct, but it could be done a little better, rather than just translating your VB code:
foreach (Control c in Panel1.Controls)
{
PictureBox picdata = c as PictureBox;
if (picdata != null)
{
...
}
}
Did you know:
That by counting the rings on a tree trunk, you can tell how many other trees it has slept with.
|
|
|
|
|
Thanks OriginalGriff
this works
thanks again for the message
|
|
|
|
|
Yep, I agree. My "Good Answer" vote goes to you.
..Go Green..
|
|
|
|
|
Aw! Thank you...
Did you know:
That by counting the rings on a tree trunk, you can tell how many other trees it has slept with.
|
|
|
|
|
I have a treeview where multiple nodes are tagged with the same tag object. When one node's text is changed, i'm using the tag object to trigger an event to change the text for all the rest of the nodes tied to this tag object. After having close to 1000 nodes tied to the same tag object, the text update takes forever. I put some print statements inside the delegate method to see how the invocation list is being executed. Well it seems that the more delegate methods registered the slower it goes from each delegate method to the next. Why would an increase in length of the invocation list slow down transition from one delegate method to the next?
|
|
|
|
|
I think that's because when you change the other nodes' text you trigger your event again, so that execution time goes up exponentially.
You need to inhibit event triggering before you start updating all the nodes, and re-enable it when you're done.
2+2=5 for very large amounts of 2
(always loved that one hehe!)
|
|
|
|
|
Moreno is likely correct. Don't trigger on the text changed, trigger on data changed.
|
|
|
|
|
I'm using AfterLabelEdit to trigger the main text change event. I also put print statements inside the custom UpdateText method of my custom TreeNode, the same UpdateText that is added as a delegate to the invocation list of the eventhandler inside the tag object. The print statements increment a counter each time text is updated. With 40 nodes to update, I get '1, 2, 3,...' and so on fairly quickly. With 1000, it take a while for each counter to print, which indicates longer time between invocation method execution. Any thoughts? thanx.
|
|
|
|
|
Can you post a code snippet ?
2+2=5 for very large amounts of 2
(always loved that one hehe!)
|
|
|
|
|
********************************************************
public class MyTreeNode: TreeNode
{...
public MyTreeNode(TagObject obj)
{
...
this.Tag = obj;
obj.TextChanged += new EventHandler(UpdateText);
...
}
public void UpdateTagText(string text)
{
((TagObject)this.Tag).Name = text;
}
public void UpdateText(object sender, EventArgs e)
{
this.Text = ((TextChangedEventArgs)e).Text; System.Diagnostics.Debug.WriteLine(((TagObject)this.Tag).c++.ToString());
}...
***********************************************************************
public class TagObject
{
public event EventHandler TextChanged;
private string name;
public int c = 0;
...
public string Name
{
get { return this.name; }
set
{
this.SetName(value);
}
}
// Invoke the TextChanged event when text changes
public void OnTextChanged(TextChangedEventArgs e)
{
if (TextChanged != null)
TextChanged(this, e);
}
private void SetName(string text)
{
this.name = text;
TextChangedEventArgs ea = new TextChangedEventArgs();
ea.Text = text;
OnTextChanged(ea);
}...
}
public class TextChangedEventArgs : EventArgs
{
private string text;
public string Text
{
get { return this.text; }
set { this.text = value; }
}
}
*****************************************************************
from the form class that contains my treeview:
...
private void treeView_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
{
((MyTreeNode)e.Node).UpdateTagText(e.label);
}
...
|
|
|
|
|
I made a few tests, and it seems the problem is not with delegate invocation.
If you disable all events and try this:
DateTime Start = DateTime.Now;
string MyLabel = "Test";
for (int i = 0; i < treeView.Nodes.Count; i++)
{
treeView.Nodes[i].Text = MyLabel;
}
TimeSpan ts = DateTime.Now.Subtract(Start);
MessageBox.Show(ts.TotalSeconds.ToString("0.000"));
You'll see it takes just the same time. So, the problem is the time the TreeNode component takes to update its text.
I tried disabiling on-screen updating, with Visible , Enabled , SuspendLayout() / ResumeLayout() and the WM_SETREDRAW window message, but it doesn't seem to gain you time.
So, I'm afraid you cannot make it faster unless you design your own TreeView / TreeNode classes optimizing them for text updating. If that's possible.
Good luck, let me know if you find any solution.
2+2=5 for very large amounts of 2
(always loved that one hehe!)
|
|
|
|
|