timer/threading

R

RobcPettit

Hi, Im using a timer every 1 second to update a datagridview, but Im
haveing problems getting it to run on a seperate thread. At the moment
the form freezes when the thread runs, I think its because im firing
the thread with in the timer, Ive tried fireing the timer from thread
start. This is my trimmed code;
private void timer1_Tick(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(liveprices));
thread.IsBackground = true;
thread.Start();
}
public delegate void onliveprices();
private void liveprices()
{
if (InvokeRequired)
{
BeginInvoke(new onliveprices(liveprices));
}
else
{
dowork
puts data into dateset and adds new rows to table
adds table to datagridview

}
}

I need to run liveprices every second, and I need to resize/move the
form. At the momment I cant because of freezing.
I tried Thread thread = new Thread(new ThreadStart(timer.start);
thread.IsBackground = true;
thread.Start(); but that froze all together.
RegardS Robert
 
M

Marc Gravell

OK; the timer (via SyncContext) fires on the UI thread. You then start
a thread, which immediately does a BeginInvoke back to the UI
thread...

At the moment you background thread is doing nothing useful; try to
split it so that it does something like:

private void liveprices()
{ // expecting this on a non-UI thread!
//TODO: go get the data into a new DataTable, array or
whatever
BeginInvoke((MethodInvoker) delegate {
//TODO: update the grid
});
}

Now the "fetch" happends on the worker thread, and the UI update
happens on the UI thread.

However, every second seems optimistic for DataTable; I'm hoping
you're using a "get changes since <x>" mechanism in the database?

And note that if your datatable is UI bound you can only touch it from
the UI thread.

Marc
 
N

Nicholas Paldino [.NET/C# MVP]

Robert,

Well, you aren't doing anything that is actually on the background
thread, since you then delegate the operation to the UI thread.

You might want to consider doing the work in the liveprices method which
creates the DataSet which you want to bind to (NOT work on the one already
attached to the grid). Then, you would call BeginInvoke, passing a delegate
which will take the DataSet you created in the background thread, and then
assigning it to the grid, something like this:

private void timer1_Tick(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(UpdateData));
// You don't really need this call.
thread.IsBackground = true;
thread.Start();
}

private void UpdateData()
{
// Do work here to create the DataSet.
// dowork
// puts data into dateset and adds new rows to table
DataSet data = ...;

if (InvokeRequired)
{
BeginInvoke(new Action<DataSet>(UpdateGrid), new object[] { data });
}
else
{
// Just call the method.
UpdateGrid(data);
}
}

private void UpdateGrid(DataSet data)
{
// Update the grid here with the data passed in.
}

This will separate the getting of the data to the background thread,
while only updating the UI when necessary.
 
R

RobcPettit

Thanks for your reply, thats improved peformance. I dont get complete
freeze. I still get it for a split second and im guessing this is
because the updates on the ui thread. My grids not linked to a
database, Im fetching data from the internet and updating the grid.
Ive no need to retain the data in a database.
Regards Robert
 
R

RobcPettit

Thanks Nicholas, Threading is complicated. Ok, Am I runderstanding
this correctly then, what I was doing was calling my thread to do all
the work, on the UI thread. When infact I should have done my work
first, then called the thread to update the UI. In which case does
this meen in general, when you preform tasks such as
calculations,fetching etc these are on seperate thread to the UI
until such time you invoke thread. Sorry I hope that makes sense.
Regards Robert
 
N

Nicholas Paldino [.NET/C# MVP]

Robert,

That's pretty much it. You want to have the thread do the work (which
is not dependent on the UI, if it is, then you need to pass the information
from the UI to the thread to operation on) and then pass the data back to
the UI (through a call to Invoke/BeginInvoke).

This is why I recommend doing the work on a separate DataSet. If you
were going to modify the DataSet bound to the grid already, then you would
have to do all that work on the UI thread, as working with a bound DataSet
causes a UI update, which in turn has to be done on the UI thread.

And yes, threading is hard. =)
 
R

RobcPettit

Thanks for taking the time to explain. Ive been doing it the wrong way
round, which explains why ive had problems with other programs. Still
its fun. Thanks again.
Regards Robert
 
M

Marc Gravell

Sorry for delay; google thinks I've exceeded my reasonable usage! Oh heck...
My grids not linked to a
database, Im fetching data from the internet and updating the grid.

Fair enough; I made an assumption, and I was wrong.
Thanks for your reply, thats improved peformance.
I'm glad things are a step better ;-p

Marc
 
R

Rene

Besides what Mark and Nicholas already said, you may want to take a look at
the:

System.Threading.Timer

If memory servese me well, this timer will use the thread pool to que its
work. It basically means that you don't have to manually start your own
thread in your "timer1_Tick" event, the timer takes care of that.

Another thing that you should be aware of (someone please correct me if I am
wrong) is that there are no guaranties on the order your multy-threaded code
will executes. For example, you can spawn thread 1, 2, 3, 4 and 5 in that
order and you may end up processing thread 5, 4, 3, 2 and 1 in that order.
 
M

Mark

Rene,

If I also remember correctly... and anyone can please correct me...

You are correct in that no thread is guaranteed to run in the order it
was launched... I do believe that you can sleep the main thread which
"helps" launch worker threads in a better "order" of processing... but
still not guaranteed...
 
R

RobcPettit

Thanks for your replys, Im reading about system.threading.timer along
with threading period. Its takes some getting into.
Regards Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top