I think that's your problem. Your Timer_Elapsed event is running on a
different thread. The Windows UI is not thread safe (not a .Net limitation,
but a Windows thing). You need to make sure that any code that affects the
UI runs on the main thread.
Your databinding code affects the UI indirectly -- when you unbind and
rebind, it implicitely causes the listbox to repaint itself. If this
repainting does not occur on the main thread, the results can be very
unpredictable (could be unresponsive controls, exceptions, or it could just
crash your application).
There are two ways around it. You could use a System.Windows.Forms.Timer
class, which (I believe) invokes its elapsed event on the main thread.
In my opinion, a better way to do this would be to use some functionality
that is built into .net to ensure that your event handler runs on the
correct thread. You are going to be interested in two methods that are
members of your form (actually, they are members of Control, and anything
that inherits Control -- including a form -- has them:
InvokeRequired(), and BeginInvoke()
InvokeRequired returns true if it is called from a thread other than the
main thread. BeginInvoke marshalls your call to the main thread without
blocking the calling thread. You can use these two items to do something
like this:
// your elapsed event handler
public void Timer_Elapsed(object sender, EventArgs e)
{
// check if invoke is required
if(this.InvokeRequired)
{
// call this method again, on the right thread
this.BeginInvoke(new EventHandler(this.Timer_Elapsed), new object[]
{sender, e});
}
else
{
// do whatever this event handler is supposed to do
}
}
Here's what's going on:
On the first pass, this event will be running on a separate thread. The
call to this.InvokeRequired will return true. We call BeginInvoke.
BeginInvoke expects a delegate to the method that should be called and an
array of object containing the parameters to be passed to the method. So, we
pass it a delegate to this method (kind of a recursive call), and we pass
the original method parameters. In the help, you will see that there is a
BeginInvoke, and an Invoke method. The difference is that BeginInvoke does
not block the calling thread, Invoke does. Some MS bloggers that I read
have advised that you use BeginInvoke unless you specifically need to block
the calling thread. This helps to avoid certain deadlock issues.
As a result of the call to BeginInvoke, Timer_Elapsed is called a second
time. This time, it is called on the main thread, so this.InvokeRequired
returns false. Execution procedes to the "else" portion of the if
statement, which is where you want to to your work with the List control.
I like this method because it is more robust -- it is guaranteed to work no
matter what kind of timer you use (or even if you use some other means, like
a background thread). On the other hand, if you use a
System.Windows.Forms.Timer, you don't need to use the Invoke code above, and
so you might get better performance.
"jayderk" <ja*****@hotmail.com> wrote in message
news:eN**************@TK2MSFTNGP12.phx.gbl...
it is of type
private System.Timers.Timer tmrPolling;
I will try and use the other timer and see if that works...
any other tips will help?
Later,
jay
"J.Marsch" <je****@ctcdeveloper.com> wrote in message
news:#u**************@TK2MSFTNGP09.phx.gbl... What kind of timer are you using, and is the timer_elapsed() event
running on the main thread? Depending upon the timer, your elapsed event might
be running on a background thread. If you do anything that affects the UI
(including setting up databinding), that code has to run on the main
thread. I'm not sure whether this would cause the problem that you are having,
but it is worth checking out.
"jayderk" <ja*****@hotmail.com> wrote in message
news:eC**************@TK2MSFTNGP12.phx.gbl... Hello All,
I am running in to a situation where the listbox is not refreshing for
me. I am using a timer to cycle every second and call the timer_elapsed()
event. in the time_elapsed event Method I have code that checks to see if a
DB table has been updated.. if so the new new data is uploaded to the listbox by calling
lstbox1.datasource = myDBDataSet;
and this works great.. but only on the first time the event gets the data from the database and loads the listbox.
the second time it goes and gets the new data from the database..
I do a
lstbox1.datasource = null; // I have to do this before I do a
lstbox1.items.clear().
lstbox1.items.clear();
this does not Clear out the list...
I then do
lstbox1.datasource = myDBDataSet;
and it does nothing....
thanks in advanced..