473,417 Members | 1,545 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,417 software developers and data experts.

Simple Threading Problem with WinForm

Hi:

I am writing a WinForm app that contains a DataGrid control and a StatusBar
control. My goal is to update the status bar using events from a separate
class, as well as some other simple things.

The method I am writing queries a large dataset. As part of my feedback to
the user, I am updating the status bar when the connection is made and the
dataset is actually retrieved. The dataset retrieval method I have placed on
a separate thread so that the status bar updates can be viewed by the user.

Everything works except for the actual binding of my dataset to the grid
control. when I attempt to bind my dataset, i get an error along the lines
of "cannot make control on parent thread of another control" or something to
that effect (I'm sorry, I dont have the actual text handy, and the query
takes a while so forgive the paraphrasing.). I am new to writing.NET
threading code, and would prefer to learn in this instance how it works and
how I broke it rather than copy and paste code, so can anyone please take a
sec and view below and tell me what I am missing? Some of the code I took
from the MSDN's Threading tutorial.

private void mnuGetDocuments_Click(object sender, System.EventArgs e)

{

if (MessageBox.Show(this, "Retrieve list of documents waiting for
printing?", "Confirm Queue Retrieval",
MessageBoxButtons.OKCancel,MessageBoxIcon.Question ) == DialogResult.OK)

{

// my events, QueueDocs is object outside of function scope.

QueueDocs.ConnectionEstablished += new
ConnectionMadeHandler(UpdateStatusOnConnection);

QueueDocs.DatasetReceived += new
DatasetReceivedHandler(UpdateStatusOnDataset);

this.sbOperationStatus.Text = "Retrieving queues... 0% complete";

// instance our new thread

Thread objThread = new Thread(new ThreadStart(this.GetDocuments));
objThread.Start();

while (!objThread.IsAlive)

{

Thread.Sleep(1);

objThread.Abort();

objThread.Join();

}

}

}

private void GetDocuments()

{

DataSet dsLocal = QueueDocs.RetrievePrintQueues();

// breaks here, on binding.

this.dgQueueDocuments.DataSource = dsLocal.Tables[0].DefaultView;

}

Thank you,
Elliot Rodriguez
Nov 17 '05 #1
3 2359
Elliot,

The reason it does not work is that you are trying to update the UI on a
thread that doesn't have the message loop for the UI. If you want to set
the data source on the datagrid (or do any other sort of updates), then you
have to create a delegate and pass it to the Invoke method on the datagrid,
and it will invoke the method, like so:

// The delegate to call the method to set the data source.
private delegate void SetDataSourceCallback(DataView view);

// The method that sets the data source.
private void SetDataSource(DataView view)
{
// Set the data source.
dgQueueDocuments.DataSource = view;
}

// This code is called in the thread.
// Your comment:
// breaks here, on binding.
dgQueueDocuments.Invoke(new SetDataSourceCallback(SetDataSource,
new object[]{dsLocal.Tables[0].DefaultView});
You will have to do this for any UI operation you want to perform from
another thread, including your update of the status bar.

A few other things. I don't understand the purpose of this code:

while (!objThread.IsAlive)
{
Thread.Sleep(1);
objThread.Abort();
objThread.Join();
}

Your thread should always be alive, and if you were waiting for the
process to kick off, you would end up sleeping for a second then aborting
it. It doesn't make sense. If you want to wait for the thread to kick off,
then use a ManualResetEvent and wait on it, and set it in the first line of
your method that is called on the new thread.

Also, if you bind to dsLocal.Tables[0], the data grid will automatically
bind to the DefaultView property on that table, it never binds to the table
directly.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Elliot Rodriguez" <el*************@geemail.com> wrote in message
news:e7**************@TK2MSFTNGP12.phx.gbl...
Hi:

I am writing a WinForm app that contains a DataGrid control and a
StatusBar control. My goal is to update the status bar using events from a
separate class, as well as some other simple things.

The method I am writing queries a large dataset. As part of my feedback to
the user, I am updating the status bar when the connection is made and the
dataset is actually retrieved. The dataset retrieval method I have placed
on a separate thread so that the status bar updates can be viewed by the
user.

Everything works except for the actual binding of my dataset to the grid
control. when I attempt to bind my dataset, i get an error along the lines
of "cannot make control on parent thread of another control" or something
to that effect (I'm sorry, I dont have the actual text handy, and the
query takes a while so forgive the paraphrasing.). I am new to writing.NET
threading code, and would prefer to learn in this instance how it works
and how I broke it rather than copy and paste code, so can anyone please
take a sec and view below and tell me what I am missing? Some of the code
I took from the MSDN's Threading tutorial.

private void mnuGetDocuments_Click(object sender, System.EventArgs e)

{

if (MessageBox.Show(this, "Retrieve list of documents waiting for
printing?", "Confirm Queue Retrieval",
MessageBoxButtons.OKCancel,MessageBoxIcon.Question ) == DialogResult.OK)

{

// my events, QueueDocs is object outside of function scope.

QueueDocs.ConnectionEstablished += new
ConnectionMadeHandler(UpdateStatusOnConnection);

QueueDocs.DatasetReceived += new
DatasetReceivedHandler(UpdateStatusOnDataset);

this.sbOperationStatus.Text = "Retrieving queues... 0% complete";

// instance our new thread

Thread objThread = new Thread(new ThreadStart(this.GetDocuments));
objThread.Start();

while (!objThread.IsAlive)

{

Thread.Sleep(1);

objThread.Abort();

objThread.Join();

}

}

}

private void GetDocuments()

{

DataSet dsLocal = QueueDocs.RetrievePrintQueues();

// breaks here, on binding.

this.dgQueueDocuments.DataSource = dsLocal.Tables[0].DefaultView;

}

Thank you,
Elliot Rodriguez

Nov 17 '05 #2
Nicholas:

Thanks for your reply.

In response to:
while (!objThread.IsAlive)
{
Thread.Sleep(1);
objThread.Abort();
objThread.Join();
}

Well, this was part of the threading tutorial I found in the MSDN. To me it
seemed it was a requirement for implementation. If youre suggesting its not
needed, then I should certainly remove it.

However, I understood this snippet to be the code that kills the thread. I
could be wrong of course.

Again, many thanks.
Elliot Rodriguez

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:ea**************@TK2MSFTNGP15.phx.gbl...
Elliot,

The reason it does not work is that you are trying to update the UI on
a thread that doesn't have the message loop for the UI. If you want to
set the data source on the datagrid (or do any other sort of updates),
then you have to create a delegate and pass it to the Invoke method on the
datagrid, and it will invoke the method, like so:

// The delegate to call the method to set the data source.
private delegate void SetDataSourceCallback(DataView view);

// The method that sets the data source.
private void SetDataSource(DataView view)
{
// Set the data source.
dgQueueDocuments.DataSource = view;
}

// This code is called in the thread.
// Your comment:
// breaks here, on binding.
dgQueueDocuments.Invoke(new SetDataSourceCallback(SetDataSource,
new object[]{dsLocal.Tables[0].DefaultView});
You will have to do this for any UI operation you want to perform from
another thread, including your update of the status bar.

A few other things. I don't understand the purpose of this code:

while (!objThread.IsAlive)
{
Thread.Sleep(1);
objThread.Abort();
objThread.Join();
}

Your thread should always be alive, and if you were waiting for the
process to kick off, you would end up sleeping for a second then aborting
it. It doesn't make sense. If you want to wait for the thread to kick
off, then use a ManualResetEvent and wait on it, and set it in the first
line of your method that is called on the new thread.

Also, if you bind to dsLocal.Tables[0], the data grid will
automatically bind to the DefaultView property on that table, it never
binds to the table directly.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Elliot Rodriguez" <el*************@geemail.com> wrote in message
news:e7**************@TK2MSFTNGP12.phx.gbl...
Hi:

I am writing a WinForm app that contains a DataGrid control and a
StatusBar control. My goal is to update the status bar using events from
a separate class, as well as some other simple things.

The method I am writing queries a large dataset. As part of my feedback
to the user, I am updating the status bar when the connection is made and
the dataset is actually retrieved. The dataset retrieval method I have
placed on a separate thread so that the status bar updates can be viewed
by the user.

Everything works except for the actual binding of my dataset to the grid
control. when I attempt to bind my dataset, i get an error along the
lines of "cannot make control on parent thread of another control" or
something to that effect (I'm sorry, I dont have the actual text handy,
and the query takes a while so forgive the paraphrasing.). I am new to
writing.NET threading code, and would prefer to learn in this instance
how it works and how I broke it rather than copy and paste code, so can
anyone please take a sec and view below and tell me what I am missing?
Some of the code I took from the MSDN's Threading tutorial.

private void mnuGetDocuments_Click(object sender, System.EventArgs e)

{

if (MessageBox.Show(this, "Retrieve list of documents waiting for
printing?", "Confirm Queue Retrieval",
MessageBoxButtons.OKCancel,MessageBoxIcon.Question ) == DialogResult.OK)

{

// my events, QueueDocs is object outside of function scope.

QueueDocs.ConnectionEstablished += new
ConnectionMadeHandler(UpdateStatusOnConnection);

QueueDocs.DatasetReceived += new
DatasetReceivedHandler(UpdateStatusOnDataset);

this.sbOperationStatus.Text = "Retrieving queues... 0% complete";

// instance our new thread

Thread objThread = new Thread(new ThreadStart(this.GetDocuments));
objThread.Start();

while (!objThread.IsAlive)

{

Thread.Sleep(1);

objThread.Abort();

objThread.Join();

}

}

}

private void GetDocuments()

{

DataSet dsLocal = QueueDocs.RetrievePrintQueues();

// breaks here, on binding.

this.dgQueueDocuments.DataSource = dsLocal.Tables[0].DefaultView;

}

Thank you,
Elliot Rodriguez


Nov 17 '05 #3
Nicholas:

I am having trouble implementing the code you posted.

I've been checking out Google and it appears that it should work, but I am
not sure why it isnt.

If I use your code as is, I get the error "Method(method name) referenced
without parentheses".

Thinking this was just an oversight, I added the parens, at which point I
thought I should pass an argument (since the method expects one), and that
breaks as well "Method name expected".

Frankly I am still very fuzzy on how threading works in .NET, so I am not
sure what to do here.

Thanks again,
Elliot
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:ea**************@TK2MSFTNGP15.phx.gbl...
Elliot,

The reason it does not work is that you are trying to update the UI on
a thread that doesn't have the message loop for the UI. If you want to
set the data source on the datagrid (or do any other sort of updates),
then you have to create a delegate and pass it to the Invoke method on the
datagrid, and it will invoke the method, like so:

// The delegate to call the method to set the data source.
private delegate void SetDataSourceCallback(DataView view);

// The method that sets the data source.
private void SetDataSource(DataView view)
{
// Set the data source.
dgQueueDocuments.DataSource = view;
}

// This code is called in the thread.
// Your comment:
// breaks here, on binding.
dgQueueDocuments.Invoke(new SetDataSourceCallback(SetDataSource,
new object[]{dsLocal.Tables[0].DefaultView});
You will have to do this for any UI operation you want to perform from
another thread, including your update of the status bar.

A few other things. I don't understand the purpose of this code:

while (!objThread.IsAlive)
{
Thread.Sleep(1);
objThread.Abort();
objThread.Join();
}

Your thread should always be alive, and if you were waiting for the
process to kick off, you would end up sleeping for a second then aborting
it. It doesn't make sense. If you want to wait for the thread to kick
off, then use a ManualResetEvent and wait on it, and set it in the first
line of your method that is called on the new thread.

Also, if you bind to dsLocal.Tables[0], the data grid will
automatically bind to the DefaultView property on that table, it never
binds to the table directly.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Elliot Rodriguez" <el*************@geemail.com> wrote in message
news:e7**************@TK2MSFTNGP12.phx.gbl...
Hi:

I am writing a WinForm app that contains a DataGrid control and a
StatusBar control. My goal is to update the status bar using events from
a separate class, as well as some other simple things.

The method I am writing queries a large dataset. As part of my feedback
to the user, I am updating the status bar when the connection is made and
the dataset is actually retrieved. The dataset retrieval method I have
placed on a separate thread so that the status bar updates can be viewed
by the user.

Everything works except for the actual binding of my dataset to the grid
control. when I attempt to bind my dataset, i get an error along the
lines of "cannot make control on parent thread of another control" or
something to that effect (I'm sorry, I dont have the actual text handy,
and the query takes a while so forgive the paraphrasing.). I am new to
writing.NET threading code, and would prefer to learn in this instance
how it works and how I broke it rather than copy and paste code, so can
anyone please take a sec and view below and tell me what I am missing?
Some of the code I took from the MSDN's Threading tutorial.

private void mnuGetDocuments_Click(object sender, System.EventArgs e)

{

if (MessageBox.Show(this, "Retrieve list of documents waiting for
printing?", "Confirm Queue Retrieval",
MessageBoxButtons.OKCancel,MessageBoxIcon.Question ) == DialogResult.OK)

{

// my events, QueueDocs is object outside of function scope.

QueueDocs.ConnectionEstablished += new
ConnectionMadeHandler(UpdateStatusOnConnection);

QueueDocs.DatasetReceived += new
DatasetReceivedHandler(UpdateStatusOnDataset);

this.sbOperationStatus.Text = "Retrieving queues... 0% complete";

// instance our new thread

Thread objThread = new Thread(new ThreadStart(this.GetDocuments));
objThread.Start();

while (!objThread.IsAlive)

{

Thread.Sleep(1);

objThread.Abort();

objThread.Join();

}

}

}

private void GetDocuments()

{

DataSet dsLocal = QueueDocs.RetrievePrintQueues();

// breaks here, on binding.

this.dgQueueDocuments.DataSource = dsLocal.Tables[0].DefaultView;

}

Thank you,
Elliot Rodriguez


Nov 17 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: GrantS | last post by:
I need urgent help. Done OK for a newbie getting automation of Windows Messenger into a Winform C# app but have three problems that I urgently need pointers to. Point 1 and 2 are the same issue, I...
10
by: Eric | last post by:
I'm looking at this page in the MSDN right here: ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist classsynchronizedtopic2.htm (or online here:...
8
by: Z D | last post by:
Hello, I'm having a strange problem that is probably due to my lack of understanding of how threading & COM Interop works in a WinForms.NET application. Here's the situation: I have a 3rd...
2
by: Sgt. Sausage | last post by:
Problem. Work-around. No issues, just looking to see if I'm the only one that's seen this. I just lost 3 hours (shoulda found it sooner) to the InvokeRequired on a form being somewhat...
11
by: Jim H | last post by:
I have work being done in worker threads and I trigger an event, that gui objects have subscribed to, when the work is complete. Will that event handler code be executed in the ui thread or the...
7
by: Anthony Nystrom | last post by:
What is the correct way to stop a thread? abort? sleep? Will it start up again... Just curious... If the thread is enabling a form, if the form is disposed is the thread as well? Thanks, ...
6
by: sklett | last post by:
In the past I've had problems with using threads and getting all kinds of weird bugs. I've been reading over Jon Skeet's GREAT website about threading and have tried to apply some of what I...
3
by: Richard MSL | last post by:
I have a C# application that works, with a main menu where the user can choose different options that run, and then return to the menu. I want to change it so that the user can starting running an...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
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...
0
Oralloy
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,...
0
jinu1996
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...
0
tracyyun
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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.