1
    private void button1_Click(object sender, EventArgs e)
    {
        PROGRESS_BAR.Minimum = 0;
        PROGRESS_BAR.Maximum = 100;
        PROGRESS_BAR.Value = 0;

        for (int i = 0; i < 100; i++)
        {
            Thread t = new Thread(new ThreadStart(updateProgressBar));
            t.IsBackground = true;
            t.Start();
        }

    }

    private void updateProgressBar()
    {   
          PROGRESS_BAR.PerformStep();
          Thread.Sleep(4000);
    }

I always get this error: Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.

I tried to search in google for solutions and unfortunately all of them didn't work for me. does any one know how to solve this? thanks in advance..

Desolator
  • 22,411
  • 20
  • 73
  • 96
  • Making one hundred threads at once is a _horrible_ idea. – SLaks Nov 14 '10 at 23:29
  • I'm just testing this. I'm still new with C#. – Desolator Nov 14 '10 at 23:32
  • You're probably misunderstanding threads. Your code creates one hundred threads that (try to) increment the progress bar at the same time. After they all (try to) increment it, they will all sleep, then exit. – SLaks Nov 14 '10 at 23:35
  • I'm trying to use it for other more "advanced" usage. besides i will be using only 5 threads at same time to process 1000+ documents. whenever 1 of the threads exits I call new one to process new document. etc.. – Desolator Nov 14 '10 at 23:40
  • 1
    Tip: Look into ThreadPool. It's made to make shure that tasks as the onece you just mentioned is as fast as possible. Just call `ThreadPool.QueueWorkerTask(delegate void())` (or something like that, just google .Net ThreadPool tutorial or something). – Alxandr Nov 14 '10 at 23:43

3 Answers3

5

You cannot interact with UI elements from non-UI thread. You need to use code like

this.BeginInvoke((Action)(() => PROGRESS_BAR.PerformStep()));
Victor Haydin
  • 3,518
  • 2
  • 26
  • 41
  • Now I get this error:Error 'System.Windows.Forms.ToolStripProgressBar' does not contain a definition for 'BeginInvoke' and no extension method 'BeginInvoke' accepting a first argument of type 'System.Windows.Forms.ToolStripProgressBar' could be found (are you missing a using directive or an assembly reference?) – Desolator Nov 14 '10 at 23:33
  • You can call `BeginInvoke` on the form itself. – SLaks Nov 14 '10 at 23:34
  • 1
    sorry, simply change PROGRESS_BAR.BeginInvoke with this.BeginInvoke – Victor Haydin Nov 14 '10 at 23:36
  • now i'm getting this error: Error Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type. – Desolator Nov 14 '10 at 23:43
2

You should use the BackgroundWorker component and its ProgressChanged event.

You can call the ReportProgress method inside the DoWork handler (which runs on the background thread), then update the progress bar in the ProgressChanged handler (which runs on the UI thread).

If you really want to do it yourself (without a BackgroundWorker), you can call BeginInvoke

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
0

All of your UI interaction, including callbacks, property sets, and method calls, must be on the same thread.

One of those callbacks can start another thread (or many threads) but they cannot directly update the UI. The way to handle the updates are through data properties. My processing thread would update a progress status property. This is throne read by the UI thread which has a timer for regular (100ms) updates of the progress bar.

If you do this, you will need a lock on any objects which are used to communicate e status updates (eg. Strings).

winwaed
  • 7,645
  • 6
  • 36
  • 81