Consider the following code in which i add nodes to a treeview control by reading an MS Access database.
Obviously, if I execute in a seperate thread I will get exception about control accessed from a thread other than the one in which it is created.
Now whenever I am adding one node to the tree I could marshel it to the GUI thread like this - void addnode(string textofnode)
-
{
-
}
The problem is that I have got some nodes which are parents of child nodes.
So we create a node and add all children of it and finally add it to treeview.
If i create the children in worker thread and send the parent to GUI thread to add it to the treeview I guess I wont be able to access those children from GUI thread(coz they are cerated in the worker thread)
How would i get around this problem? - TreeNode extensions = new TreeNode("Extensions");
-
treeexchange.Nodes.Add(extensions);
-
-
DataTable dtgroups = new DataTable("Groups"); //get groups
-
OleDbDataAdapter adp = new OleDbDataAdapter("select * from t_extensiongroups", @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\exchangesandtrunks.mdb;Persist Security Info=False");
-
adp.Fill(dtgroups);
-
-
for (int i = 0; i < dtgroups.Rows.Count; i++)//for all the groups
-
{
-
//create a groupnode with the group name in it
-
TreeNode group = new TreeNode(dtgroups.Rows[i][0].ToString());
-
-
//get no of extensions corresposnding to that group
-
adp = new OleDbDataAdapter("select * from t_extensions where group_name='" + dtgroups.Rows[i]["groups"].ToString() + "'", @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\exchangesandtrunks.mdb;Persist Security Info=False");
-
DataTable dtextensions = new DataTable("Extensions");
-
adp.Fill(dtextensions);
-
-
//add all the extension nodes to the groupnode
-
for (int j = 0; j < dtextensions.Rows.Count; j++)
-
{
-
group.Nodes.Add(dtextensions.Rows[j]["name"].ToString() + " (" + dtextensions.Rows[j]["number"].ToString() + ")");
-
}
-
-
//add the group
-
extensions.Nodes.Add(group);
-
}
-
-
//create a trunk node
-
TreeNode trunks = new TreeNode("Trunks");
-
-
//get trunks
-
adp = new OleDbDataAdapter("select connected_trunk,name from t_trunk_lines", @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\exchangesandtrunks.mdb;Persist Security Info=False");
-
DataTable dttrunks = new DataTable("Trunks");
-
adp.Fill(dttrunks);
-
-
//add all trunks to the trunk node
-
for (int i = 0; i < dttrunks.Rows.Count; i++)
-
{
-
trunks.Nodes.Add(dttrunks.Rows[i]["name"].ToString() + " (" + dttrunks.Rows[i]["connected_trunk"].ToString() + ")");
-
}
-
-
//add the trunk node
-
treeexchange.Nodes.Add(trunks);
-
-
//add the pbx node
-
treeexchange.Nodes.Add("My PBX");
-
-
treeexchange.Nodes.Add("User");
16 2715
Your code is unformatted and very difficult to read.
When updating controls on a WinForm from a thread, use a derivative of Control.Invoke to update the control.
A very safe way to update controls on a WinForm is to spawn the thread using a BackgroundWorke r component.
Here is a great article discussing thread updating WinForms: Threading in Windows Forms.
Here is the formatted code : - treeexchange.Nodes.Clear();
-
TreeNode extensions = new TreeNode("Extensions");
-
treeexchange.Nodes.Add(extensions);
-
-
DataTable dtgroups = new DataTable("Groups"); //get groups
-
OleDbDataAdapter adp = new OleDbDataAdapter("select * from t_extensiongroups", @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\exchangesandtrunks.mdb;Persist Security Info=False");
-
adp.Fill(dtgroups);
-
-
for (int i = 0; i < dtgroups.Rows.Count; i++)//for all the groups
-
{
-
//create a groupnode with the group name in it
-
TreeNode group = new TreeNode(dtgroups.Rows[i][0].ToString());
-
-
//get no of extensions corresposnding to that group
-
adp = new OleDbDataAdapter("select * from t_extensions where group_name='" + dtgroups.Rows[i]["groups"].ToString() + "'", @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\exchangesandtrunks.mdb;Persist Security Info=False");
-
DataTable dtextensions = new DataTable("Extensions");
-
adp.Fill(dtextensions);
-
-
//add all the extension nodes to the groupnode
-
for (int j = 0; j < dtextensions.Rows.Count; j++)
-
{
-
group.Nodes.Add(dtextensions.Rows[j]["name"].ToString() + " (" + dtextensions.Rows[j]["number"].ToString() + ")");
-
}
-
-
//add the group
-
extensions.Nodes.Add(group);
-
}
-
-
//create a trunk node
-
TreeNode trunks = new TreeNode("Trunks");
-
-
//get trunks
-
adp = new OleDbDataAdapter("select connected_trunk,name from t_trunk_lines", @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\exchangesandtrunks.mdb;Persist Security Info=False");
-
DataTable dttrunks = new DataTable("Trunks");
-
adp.Fill(dttrunks);
-
-
//add all trunks to the trunk node
-
for (int i = 0; i < dttrunks.Rows.Count; i++)
-
{
-
trunks.Nodes.Add(dttrunks.Rows[i]["name"].ToString() + " (" + dttrunks.Rows[i]["connected_trunk"].ToString() + ")");
-
}
-
-
//add the trunk node
-
treeexchange.Nodes.Add(trunks);
-
-
//add the pbx node
-
treeexchange.Nodes.Add("My PBX");
-
-
treeexchange.Nodes.Add("User");
I will make two suggestions, but I have not written an example to prove they will work correctly. Let me know if they do not.
Suggestion #1: - Instantiate the initial TreeView in the GUI.
- Pass it as a parameter to a BackgroundWorke r thread (also created in the GUI).
- Have the thread fill in the nodes (your posted code).
- Handle the RunWorkerComple ted event to update the actual display of the filled-in TreeView.
- How To: Run an Operation in the Background.
Suggestion #2:
If you still receive a thread access violation after implementing the above, then add a helper method to your GUI which will clone the nodes created in the thread to the nodes in your GUI TreeView. This can be a simple recusion loop and should run quickly, since you have already performed the data access part in your thread.
However, I truly believe the second step will not be necessary. If you spawn a BackgroundWorke r thread from the GUI, it is guaranteed to execute on the same thread as the GUI itself. It is provided in the Component namespace specifically to eliminate the cross-threading issues associated with WinForms.
@mldisibio
Actually the task you specify to DoWork is run on a separate thread. That's why the interface remains responsive. The key thing is to make sure that you don't do any GUI updates from DoWork. If intermediate GUI updates are required as in this case then the OnProgressChang ed method should be used which raises the ProgressChanged event. This allows you to queue the interface updates to the UI interface thread.
I'm guessing you want something alone the lines of : -
delegate void AddNodeDelegate(string nodeName);
-
-
void AddNode(string nodeName)
-
{
-
if(treeexchange.InvokeRequired)
-
{
-
AddNodeDelegate addDelegate = new AddNodeDelegate(AddNode);
-
this.Invoke(addDelegate, new object[] { nodeName });
-
}
-
else
-
{
-
this.treeexchange.Nodes.Add(nodeName);
-
}
-
}
-
Your alternative (which I don't like)... is to not do the work in a background thread at all. And put the following in appropriate places to refresh your GUI.
.... And yes, as you say, interface updates must be done via the RunWorkerComple ted event, and optionally the ProgressChanged event if desired.
@mldisibio
If I add nodes in the BackgroundWorke r thread then will I be able to access them from the main GUI thread ?
In some code i am reading the Text of the nodes.
.... And yes, as you say, interface updates must be done via the RunWorkerComple ted event, and optionally the ProgressChanged event if desired.
Not precisely. The RunWorkerComple ted is used to update the interface when the background task has completed while the ProgressChanged is used for updating the interface while the background task is still running. It's a way for providing intermediate results of the ask to the interface.
EDIT:mldisibio, I'm terribly sorry that I have messed up your response above. I accidentally clicked the edit button when I wanted to click the quote button so in the end I ended up deleting the first and last parts of your post. Only the part that I quoted now remains!
Please feel free to post it again if you wish.
No problem. For the record I simply corrected my original post, agreeing with your response: the DoWork thread is indeed a separate thread, not the same as the UI thread, but spawing the BackgroundWorke r from the UI guarantees that the worker thread will be correctly marshalled back to the UI thread.
A great link on this subject from Alhahari: Threading in C# - Part 3 - Using Threads Sign in to post your reply or Sign up for a free account.
Similar topics |
by: Mark Hoffman |
last post by:
All,
My application spawns a worker process by calling BeginInvoke with an
asynchronous callback method. This callback method is responsible for
calling EndInvoke. No problems there; pretty much straight out of MSDN.
My question is what happens when my worker thread raises an exception? I can
easily catch the exception, but I've noticed that unless my async callback
runs and EndInvoke gets called, then the worker thread never gets...
|
by: Jeff Stewart |
last post by:
I need a thread to run a subroutine which updates my main form's
progress bar. I've properly marshaled all UI updates to the main UI
thread, and after the main thread starts the worker thread, it waits
for the worker thread to complete by means of a while t.isAlive,
sleep(0) mechanism. But when my worker thread calls my
UpdateProgressBar routine, which calls Me.Invoke, the invoke call
blocks forever. But I can't figure out why the main...
|
by: Charles Law |
last post by:
My first thought was to call
WorkerThread.Suspend
but the help cautions against this (for good reason) because the caller has
no control over where the thread actually stops, and it might have a lock
pending, for example.
I want to be able to stop a thread temporarily, and then optionally resume
it or stop it for good.
|
by: hazz |
last post by:
What happens if I set the timer interval for a period that is less than the
time it will take to process the loop below? Right now my application is
returning just a few items in an arraylist to process but the process should
scale to 100 or even 1000 loops. If the functions contained within the loop,
some of which go out to web services, take an indeterminate amount of time,
how do I design my windows service so that if the code takes...
|
by: Joe Jax |
last post by:
I have an object that spawns a worker thread to process one of its methods.
That method processes methods on a collection of other objects. During this
processing, a user may request to cancel the entire operation. I could
request abort on the worker thread, but that is a) potentially messy, and b)
not guaranteed to take immediate effect anyway. I would rather have some way
of allowing the main thread to tell the worker thread that it...
| |
by: Soren S. Jorgensen |
last post by:
Hi,
In my app I've got a worker thread (background) doing some calculations
based upon user input. A new worker thread might be invoked before the
previous worker thread has ended, and I wan't only one worker thread running
at any time (if a new worker thread start has been requested, any running
worker thread results will be invalid). I'm using the below method to invoke
a new worker thread, but when stress testing this I'm sometimes...
|
by: joey.powell |
last post by:
I am using VS2005 for a windows forms application. I need to be able to
use a worker thread function to offload some processing from the UI
thread. The worker thread will need access to a datagridview on the
form. I am using the following code to spawn the worker thread...
Thread WorkerThread = new Thread(new ThreadStart(WT_MyFunction));
WorkerThread.IsBackground = true;
WorkerThread.Start();
The problem I am having is...I cannot seem...
|
by: =?Utf-8?B?aGVyYmVydA==?= |
last post by:
I read from a serialport using a worker thread. Because the worker thread t
does not loop often, I cannot wait to terminate the worker thread using a
boolean in the While condition.
So I have a StopReader() method that simply aborts the worker thread (is
there a better way for the above situation?).
The StopReader creates an ObjectDisposedException when calling t.Abort(). WHY?
Public Sub StopReader()
|
by: dgleeson3 |
last post by:
Hello all
Yes I know its been done before, but something silly is killing me on
this.
I have the standard progress bar and worker thread scenario with
progress of the worker thread being fed back to the main UI and
displayed on the progress bar. I have a delegate and am using
BeginInvoke. But the progress bar is not updating.
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
| |
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |