|
Subject:
|
Cross-thread operation not valid
|
|
Posted By:
|
Richw71
|
Post Date:
|
12/13/2006 8:17:28 AM
|
Hi,
I have a form that, on clicking a button, kicks off a thread. That thread raises occasional events that I want the original form to trap and show information about.
Everything seems perfectly logical to me, but at run-time I get an error: Cross-thread operation not valid.
The solutions that I have seen work for the case where the code to update the form is contained within the thread itself. In my case, though, I want the thread class to be reusable without modification and so do not want to code references to a particular form inside the thread.
Here is the code, in the form, that uses the thread:
// This is my UI class: the standard VS2005 created "Form1"
// The form contains a button: button1, and a label: label1
/* Info:
* When the button1 is clicked a thread is created that
* performs a long calculation. From time-to-time during
* the calculation an event - ChangedResult - is raised and
* this event passes back the current result to the calling
* form for display in label1
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace TestCrossThreadApp1
{
public partial class Form1 : Form
{
// Default constructor... no surprises
public Form1()
{
InitializeComponent();
}//Form1
// The button click event that creates an instance of a "calc" thread
// an event handling method, onChangedResult, is setup to received
// the ChangedResult event from the Calc1 thread.
private void button1_Click(object sender, EventArgs e)
{
MyCalcThread Calc1 = new MyCalcThread();
Calc1.ChangedResult += onChangedResult;
Calc1.StartCalculation();
}// button1_click
// The onChangedResult method is called by delegation
private void onChangedResult(object sender, CalcEventArgs CEA)
{
string s = Convert.ToString(CEA.Result);
label1.Text = s; //<-------- This is where the ERROR occurs!
}// onChangedResult
}// class Form1
}// Namespace
The following is the code for the thread object and it's eventargs object:
using System;
using System.Threading;
namespace TestCrossThreadApp1
{
// Define the delegate for the ChangedResult event
public delegate void ChangedResultHandler(object sender, CalcEventArgs CEA);
// Event Arguments
public class CalcEventArgs : EventArgs
{
private int result;
// Constructor
public CalcEventArgs(int Result)
{
this.result = Result;
} // Constructor
// Get Parameter
public int Result
{
get
{
return result;
} // Get
} // Get Parameter
}//class CalcEventArgs
// Declare a class that encapsulates the threaded calculations
public class MyCalcThread
{
// Define an event that will be fired when the calculation result is changed significantly
public event ChangedResultHandler ChangedResult;
// This method creates an instance of the event args and raises the ChangedResult event
public void RaiseResultChangedEvent(int Result)
{
CalcEventArgs CEA = new CalcEventArgs(Result);
ChangedResult(this, CEA);
}// RaiseResultChangedEvent
// Public class that starts the calculation in it's own thread
public void StartCalculation()
{
Thread CalculationThread = new Thread(new ThreadStart(CalcThread));
CalculationThread.Start();
}// StartCalculation
// This is a mundane "calculation"
public void CalcThread()
{
int i = 0;
while (++i < 10000000)
{
// Raise the ChangedEvent method via the RaiseResultChangedEvent wrapper
switch (i)
{
case 1:
case 100000:
case 500000:
case 1000000:
RaiseResultChangedEvent(i);
break;
} // switch
}// While
}// CalcThread
}// Class MyCalcThread
}// Namespace
This is very frustrating, so any help that you could offer would be appreciated!
- Rich
|
|