A
Arthur
I developed a simple windows forms application (for controlling a
service application).
As there are no events of the ServiceController class (e.g. "State of
the service applioaction has changed") the forms application can
subscribe to, it polls the state of the service through the
ServiceController class every one seconds.
This is done by a Timer object "t" with a "t_elapsed" eventhandler
subscribed to the "elapsed" event.
When the eventhandler tries to update controls of the form an
exception is thrown, as the controls belong to another thread than the
one where the "t_elapsed" eventhandler runs. the eventhandler runs in
the "Timer" thread as far as i understood the matter.
So far everything works as we all expected it.
Here is a codeexample for the above described:
public partial class Form1 : Form
{
ServiceController sc;
public System.Timers.Timer t;
public Form1()
{
InitializeComponent();
this.sc = new ServiceController("SomeService");
this.t = new System.Timers.Timer(1000);
this.t.Elapsed += new ElapsedEventHandler(t_Elapsed);
this.t.Start();
}
protected void t_Elapsed(object sender, ElapsedEventArgs e)
{
//cannot update controls of the form from here.
}
}
The msdn2 says, the prefered way to solve cross thread control access
issues is to use a backgroundworker. And it plots the way like this:
..add a backgroundworker to the form
..register a handler for its "RunWorkerCompleted" event
..call the "RunWorkerAsync" method, when something needs to be done
..do the updating of the controls safely from the handler that
subscribes to the "RunWorkerCompleted" event
....which imediately arouse the question "Why should this work as the
handler will as well run in another thread than the one that owns the
controls?"
And indeed, it doesn't work this way either.
Here is a code example for the 2nd try:
public partial class Form1 : Form
{
ServiceController sc;
public System.Timers.Timer t;
public Form1()
{
InitializeComponent();
this.sc = new ServiceController("MyFirstService");
this.t = new System.Timers.Timer(1000);
this.t.Elapsed += new ElapsedEventHandler(t_Elapsed);
this.t.Start();
}
protected void t_Elapsed(object sender, ElapsedEventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object
sender, RunWorkerCompletedEventArgs e)
{
//cannot access forms controls from here either
}
}
So what about the backgroundworker? Can anyone explain the pros of the
BGWorker to me and why it does not work in my example (or better, how
i should put it to work)?
My actual solution - which works - is to use "BeginnInvoke" in
"t_elapsed" to access the controls through the UI thread.
But i would like to gather knowledge and wisdom about the BGWorker
solution too
Thanks in advance,
Arthur
service application).
As there are no events of the ServiceController class (e.g. "State of
the service applioaction has changed") the forms application can
subscribe to, it polls the state of the service through the
ServiceController class every one seconds.
This is done by a Timer object "t" with a "t_elapsed" eventhandler
subscribed to the "elapsed" event.
When the eventhandler tries to update controls of the form an
exception is thrown, as the controls belong to another thread than the
one where the "t_elapsed" eventhandler runs. the eventhandler runs in
the "Timer" thread as far as i understood the matter.
So far everything works as we all expected it.
Here is a codeexample for the above described:
public partial class Form1 : Form
{
ServiceController sc;
public System.Timers.Timer t;
public Form1()
{
InitializeComponent();
this.sc = new ServiceController("SomeService");
this.t = new System.Timers.Timer(1000);
this.t.Elapsed += new ElapsedEventHandler(t_Elapsed);
this.t.Start();
}
protected void t_Elapsed(object sender, ElapsedEventArgs e)
{
//cannot update controls of the form from here.
}
}
The msdn2 says, the prefered way to solve cross thread control access
issues is to use a backgroundworker. And it plots the way like this:
..add a backgroundworker to the form
..register a handler for its "RunWorkerCompleted" event
..call the "RunWorkerAsync" method, when something needs to be done
..do the updating of the controls safely from the handler that
subscribes to the "RunWorkerCompleted" event
....which imediately arouse the question "Why should this work as the
handler will as well run in another thread than the one that owns the
controls?"
And indeed, it doesn't work this way either.
Here is a code example for the 2nd try:
public partial class Form1 : Form
{
ServiceController sc;
public System.Timers.Timer t;
public Form1()
{
InitializeComponent();
this.sc = new ServiceController("MyFirstService");
this.t = new System.Timers.Timer(1000);
this.t.Elapsed += new ElapsedEventHandler(t_Elapsed);
this.t.Start();
}
protected void t_Elapsed(object sender, ElapsedEventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object
sender, RunWorkerCompletedEventArgs e)
{
//cannot access forms controls from here either
}
}
So what about the backgroundworker? Can anyone explain the pros of the
BGWorker to me and why it does not work in my example (or better, how
i should put it to work)?
My actual solution - which works - is to use "BeginnInvoke" in
"t_elapsed" to access the controls through the UI thread.
But i would like to gather knowledge and wisdom about the BGWorker
solution too
Thanks in advance,
Arthur