InvalidOperationException:"Cross-thread operation not valid: Control '<name>' accessed from a thread other than the thread it was created on."This exception is something often seen by someone who needs work done on a background thread to leave the application UI responsive to users and maybe even allow the user to cancel the current opperation, while changing properties of controls on the UI from within the background opperation. I will explain in this a solution in dealing with this particular problem, given a scenario in which the solution is appopriate, where I use extension methods to provide a general solution to the problem.Background It should be noted that when particular opperations need to be executed in the background, a the BackgroundWorker is by far the best way to accomplish this.However, it is not always possible to use the background worker 'as is' and you could even have a need to write your own thread handling classes. This is where the following extension method comes in handy. The problemConsider the scenario in which you want to wrap a BackgroundWorker and provide an extra event that reports a status message of the work being done in the worker.public class ThreadedCall
{
public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);
{
{
// The worker being wrapped by our class
private BackgroundWorker bw;// Our new event that will be called whenever our class wants to report a status
public event StatusChangedEventHandler StatusChanged;// The entry point of our class to start background opperation
public void Start()
{
bw = new BackgroundWorker();bw.DoWork += new DoWorkEventHandler(bw_DoWork);bw.RunWorkerAsync();
}// The method that does the actual work, run inside our wrapped worker
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// Report a status hereif (StatusChanged!= null) StatusChanged.Invoke(this,new StatusChangedEventArgs("Phase 1"));
Thread.Sleep(100); // Do some work
// Report another status hereif (StatusChanged!= null) StatusChanged.Invoke(this,new StatusChangedEventArgs("Phase 2"));
}}Our event handler code:// Delegate to eventhandler that takes a StatusChangedEventArgs as paramater
public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);
public class StatusChangedEventArgs : EventArgs
{
{
private string status;// The status property added to the eventargs used to supply status to the calleepublic string Status{
get { return status; }set { status = value; }
}public StatusChangedEventArgs(string status){
this.status = status;
}
}
Some code to test our class (The UI code): private void button1_Click(object sender, EventArgs e)
{
{
// Instantiate and start or worker wrapper}
ThreadedCall t = new ThreadedCall();
t.StatusChanged += new StatusChangedEventHandler(t_StatusChanged);
t.Start();
void t_StatusChanged(object sender, StatusChangedEventArgs e)
{
// The following line will raise an exception!textBox1.Text = string.Format("Status: {0}", e.Status);
}
Read more: Codeproject
Read more: Codeproject
0 comments:
Post a Comment