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


Go to topic 5989

Return to index page 95
Return to index page 94
Return to index page 93
Return to index page 92
Return to index page 91
Return to index page 90
Return to index page 89
Return to index page 88
Return to index page 87
Return to index page 86