|
It still has the same isse.
I'm not sure I understood your suggestion, but I updated it as shown below. However, the gui still hangs while loading the companies.
public void LoadCompanies()
{
if (pnlNavigation.InvokeRequired)
{
LoadCompaniesDelegate find = new LoadCompaniesDelegate(LoadCompanies);
this.Invoke(find, new object[] { });
}
else
{
PROSOCO.Library.Companies.Criteria criteria = PROSOCO.Library.Companies.Criteria.GetCriteria();
BindingSource src = new BindingSource();
PROSOCO.Library.Companies.Nodes nodes = PROSOCO.Library.Companies.Nodes.GetNodes(criteria.NodeCriteria());
src.DataSource = nodes;
pnlNavigation.ContentTree.ParentMember = "ParentId";
pnlNavigation.ContentTree.ValueMember = "Id";
pnlNavigation.ContentTree.DisplayMember = "Name";
pnlNavigation.ContentTree.PrefixMember = "CustomerNumber";
pnlNavigation.ContentTree.PostfixMember = "CityState";
pnlNavigation.ContentTree.DataSource = src;
}
_activeModule = "Companies";
}
|
|
|
|
|
This still makes it execute on the GUI thread.
One idea would be to run everything but the actual GUI stuff in the background. When BackgroundWorker finishes, you can return the data that you need to load the GUI stuff (Binding Source) through the DoWorkEventArgs.Result (which gets sent to the RunWorkerCompletedEvent when it finish DoWork). You then cast the Result to a BindingSource and do the last portion of your code (after src.DataSource = nodes; ) in the GUI thread.
|
|
|
|
|
I am new to C# so forgive me for not "just getting it" but this is what I have so far. I am doing something wrong because "BindingSource src = (BindingSource)e.Result;" Doesn't seem to be loading any data...
Did I atleast get everything running in the background except the GUI stuff?
Can you tell why I wouldn't be loading any data?
Thanks in advance.
<br />
private delegate object LoadCompaniesDelegate();<br />
<br />
public object LoadCompanies()<br />
{<br />
BindingSource src = new BindingSource();<br />
if (pnlNavigation.InvokeRequired)<br />
{<br />
LoadCompaniesDelegate find = new LoadCompaniesDelegate(LoadCompanies);<br />
this.Invoke(find, new object[] { });<br />
}<br />
else<br />
{<br />
PROSOCO.Library.Companies.Criteria criteria = PROSOCO.Library.Companies.Criteria.GetCriteria(); <br />
PROSOCO.Library.Companies.Nodes nodes = PROSOCO.Library.Companies.Nodes.GetNodes(criteria.NodeCriteria()); <br />
src.DataSource = nodes;<br />
MessageBox.Show("Loaded Notes");<br />
}<br />
return src;<br />
} <br />
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)<br />
{<br />
e.Result = LoadCompanies();<br />
}<br />
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)<br />
{<br />
BindingSource src = (BindingSource)e.Result;<br />
pnlNavigation.ContentTree.ParentMember = "ParentId";<br />
pnlNavigation.ContentTree.ValueMember = "Id";<br />
pnlNavigation.ContentTree.DisplayMember = "Name";<br />
pnlNavigation.ContentTree.PrefixMember = "CustomerNumber";<br />
pnlNavigation.ContentTree.PostfixMember = "CityState";<br />
pnlNavigation.ContentTree.DataSource = src;<br />
_activeModule = "Companies";<br />
<br />
MessageBox.Show("Completed");<br />
} <br />
|
|
|
|
|
Remove the
---
if (pnlNavigation.InvokeRequired)
{
LoadCompaniesDelegate find = new LoadCompaniesDelegate(LoadCompanies);
this.Invoke(find, new object[] { });
}
else
{
--
Don't touch anything that has to do with a GUI element inside of your background worker DoWork for now... just keep what you have in RunWorkerCompleted.
Currently it is taking the first path (InvokeRequired path), so the data won't be loaded into the BindingSource (since that is done in the Else) part.
|
|
|
|
|
Thank you Phil.
I still get the (Not Responding) for a couple seconds when it gets to "pnlNavigation.ContentTree.DataSource = src;" This is a lot of data to load. Since it is taking the most time, shouldn't that part be inside bgWorker_DoWork? ... but it cannot because it is updating the GUI ... so I don't konw what to do.
|
|
|
|
|
What do you think about this explanation?
The freezing is because the control is being filled out by the data source, and the only thread allowed to do that is the UI. So, if your data source is large there isn't a way around the 2 seconds pause... unless...
You could manually fill out your control by looping over the data source yourself, and every 10 or so, do a DoEvents() call to keep the UI fresh.
|
|
|
|
|
justin.moses wrote: So, if your data source is large there isn't a way around the 2 seconds pause... unless...
If your data set is too large to be displayed all at once, your best bet is filling the dataset a few rows at a time, preferrably in the Application.Idle event handler.
p.s. don't use DoEvents(). It's evil, trust me.
|
|
|
|
|
No, that is not how I explained it; the else part executes on the GUI thread and
hence must be fast. Take out everything that does not need to be there, and
have it execute before you call public void LoadCompanies().
|
|
|
|
|
I'm not quite sure what the LoadCompanies is supposed to be doing, but focus on this part:
if (pnlNavigation.InvokeRequired)
{
LoadCompaniesDelegate find = new LoadCompaniesDelegate(LoadCompanies);
this.Invoke(find, new object[] { });
}
else
{
pnlNavigation.ContentTree.ParentMember = "ParentId";
pnlNavigation.ContentTree.ValueMember = "Id";
pnlNavigation.ContentTree.DisplayMember = "Name";
pnlNavigation.ContentTree.PrefixMember = "CustomerNumber";
pnlNavigation.ContentTree.PostfixMember = "CityState";
pnlNavigation.ContentTree.DataSource = src;
}
As you can see by the comments, the BackgroundWorker will indeed run LoadCompanies on its own thread. You then check for InvokeRequired -- since crossthreaded operations are illegal, this function returns true if the object is on another thread. If it is (which I'm guessing pnlNavigation is a GUI element on the GUI thread), you then call Invoke to call LoadCompanies, which forces it to run on the GUI thread! So you're back where you started, and you have to load from the database AGAIN!
|
|
|
|
|
I changed LoadCompanies so as best I can tell, it isn't loading anything twice.
It still has the same (not responding) issue while it loads all the records into the ContentTree.
public void LoadCompanies()
{
if (pnlNavigation.InvokeRequired)
{
LoadCompaniesDelegate find = new LoadCompaniesDelegate(LoadCompanies);
this.Invoke(find, new object[] { });
}
else
{
PROSOCO.Library.Companies.Criteria criteria = PROSOCO.Library.Companies.Criteria.GetCriteria();
BindingSource src = new BindingSource();
PROSOCO.Library.Companies.Nodes nodes = PROSOCO.Library.Companies.Nodes.GetNodes(criteria.NodeCriteria());
src.DataSource = nodes;
pnlNavigation.ContentTree.ParentMember = "ParentId";
pnlNavigation.ContentTree.ValueMember = "Id";
pnlNavigation.ContentTree.DisplayMember = "Name";
pnlNavigation.ContentTree.PrefixMember = "CustomerNumber";
pnlNavigation.ContentTree.PostfixMember = "CityState";
pnlNavigation.ContentTree.DataSource = src;
}
_activeModule = "Companies";
}
|
|
|
|
|
Yes, the double loading was only one problem. Invoke forces it to run on the thread of the object that you called it from.
|
|
|
|
|
Try changing the LoadCompanies method to this instead:
public void LoadCompanies(DoWorkEventArgs e)
{
PROSOCO.Library.Companies.Criteria criteria = PROSOCO.Library.Companies.Criteria.GetCriteria();
BindingSource src = new BindingSource();
PROSOCO.Library.Companies.Nodes nodes = PROSOCO.Library.Companies.Nodes.GetNodes(criteria.NodeCriteria());
src.DataSource = nodes;
e.Result = src;
}
Then change your RunWorkerCompleted handler to look like this:
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BindingSource src = (BindingSource)e.Result;
pnlNavigation.ContentTree.ParentMember = "ParentId";
pnlNavigation.ContentTree.ValueMember = "Id";
pnlNavigation.ContentTree.DisplayMember = "Name";
pnlNavigation.ContentTree.PrefixMember = "CustomerNumber";
pnlNavigation.ContentTree.PostfixMember = "CityState";
pnlNavigation.ContentTree.DataSource = src;
ShowLoadingAnimation(false);
_activeModule = "Companies";
}
|
|
|
|
|
It is still freezing the GUI. Let me know if I am doing this how you reccomended or not.
Here is what I have:
private void LoadCompanies(object sender, EventArgs e)<br />
{<br />
pnlNavigation.ShowLoader(true);<br />
this.bgWorker.RunWorkerAsync();<br />
}<br />
<br />
private delegate object LoadCompaniesDelegate();<br />
<br />
public void LoadCompanies(DoWorkEventArgs e)<br />
{<br />
PROSOCO.Library.Companies.Criteria criteria = PROSOCO.Library.Companies.Criteria.GetCriteria();<br />
BindingSource src = new BindingSource();<br />
PROSOCO.Library.Companies.Nodes nodes = PROSOCO.Library.Companies.Nodes.GetNodes(criteria.NodeCriteria());<br />
src.DataSource = nodes;<br />
e.Result = src;<br />
}<br />
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)<br />
{<br />
LoadCompanies(e);<br />
}<br />
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) <br />
{<br />
BindingSource src = (BindingSource)e.Result;<br />
pnlNavigation.ContentTree.ParentMember = "ParentId";<br />
pnlNavigation.ContentTree.ValueMember = "Id";<br />
pnlNavigation.ContentTree.DisplayMember = "Name";<br />
pnlNavigation.ContentTree.PrefixMember = "CustomerNumber";<br />
pnlNavigation.ContentTree.PostfixMember = "CityState";<br />
pnlNavigation.ContentTree.DataSource = src;<br />
pnlNavigation.ShowLoader(false);<br />
_activeModule = "Companies"; <br />
}
|
|
|
|
|
Stick in some debug statements to see where it is slowing down on.
|
|
|
|
|
I get the (Not Responding) for a couple seconds when it gets to "pnlNavigation.ContentTree.DataSource = src;" This is a lot of data to load, however, I thought the background worker would handle that. Right?
|
|
|
|
|
To eliminate possibilities, temporarily comment all code inside RunWorkerCompleted handler. Does it still freeze?
|
|
|
|
|
Hi all,
I managed to set the forecolor of a Disabled Label by overriding the OnPiant method but how to get automatic text handling (autoelipsis = true & autosize = false) to work ?
T.I.A.
|
|
|
|
|
You took over painting of the control, so you've got to determine what conditions have to be met and what to draw for each situation. You can't do "just this piece" and expect the control to draw what you didn't. You either have to draw it all, or let the control draw itself, then you draw over the top of it. Warning! Taking the second route could result in some very unexpected results!
|
|
|
|
|
I was thinking that someone would kindly enough to share some code with me so i can get faster in my project than your answer as no answer
|
|
|
|
|
I pointed you in the right direction, it's up to you to paint the control how you want it. Check into the MeasureString method of the Graphics object you're using to draw with.
patkan wrote: someone would kindly enough to share some code with me so i can get faster in my project
That's not how CP works. YOU write the code and learn by doing. When you get stuck, you ask specific questions about the problem. You learn nothing by us writing the code for you.
|
|
|
|
|
What's a "Disabled Label"? What do Labels do that can be enabled and disabled? What's the point of setting Enabled to false on a Label? And if you did, why then would you modify what it looks like?
|
|
|
|
|
PIEBALDconsult wrote: What's a "Disabled Label"?
I was wondering that, too. He might be meaning a text box? I am not sure.
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
|
|
|
|
|
see my reply to PIEBALDconsult
|
|
|
|
|
I've created a user control class, to make the click event for this control to function well (any lazy to set on all the other controls click event), i have to disabled all the label,textbox,images & etc controls
Sorry for poor english
Patrick
|
|
|
|
|
I still have no idea what you mean.
|
|
|
|