-1

I am fighting with a tutorial from here:

https://www.geeksforgeeks.org/c-sharp-multithreading/

I try to reuse this code with windows forms, but with no success. I have modified the code to this form, using two richtextboxes:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace Multithreading
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    {
        public MainForm()
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();
            
            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //
            Thread thr1 = new Thread(method1);
            Thread thr2 = new Thread(method2);
            
            thr1.Start();
            thr2.Start();
        }

        public void method1()
        {
            // It prints numbers from 0 to 10
            for (int I = 0; I <= 10; I++) 
            {
                richTextBox1.Text += "Method1 is: "+ I  + Environment.NewLine;  

                if (I == 5)
                {
                    Thread.Sleep(6000);
                }
            }
        }
 
        public void method2()
        {
            // It prints numbers from 0 to 10
            for (int J = 0; J <= 10; J++) 
            {
                richTextBox2.Text += "Method2 is: "+ J  + Environment.NewLine;  
            }
        }
    }
}

...and I get an error after 6 seconds:

Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on

I can't get why the first five numbers can be read (method 1) and all numbers from method 2 too, and after Thread.Sleep(6000) there is an error :(

It's my first time with multithreading, any help will be appreciated.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Karlsson
  • 15
  • 3
  • see https://stackoverflow.com/questions/10775367/cross-thread-operation-not-valid-control-textbox1-accessed-from-a-thread-othe – klekmek Sep 20 '22 at 13:27
  • This code is broken. You can't modify the UI from a background thread *in any operating system*. There are a *lot* of duplicate SO questions with solutions. All Winforms articles, tutorials and books explain how to use tasks and async/await at some point. The posted answer actually explains how to fix this problem. – Panagiotis Kanavos Sep 20 '22 at 13:49
  • The [question](https://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) that is linked (correctly) as duplicate contains many outdated answers. You might find better solutions to the "Cross-thread operation not valid" problem in questions about async/await or the `BackgroundWorker` class, like [this](https://stackoverflow.com/questions/12414601/async-await-vs-backgroundworker/64620920#64620920 "Async/await vs BackgroundWorker") for example. – Theodor Zoulias Sep 20 '22 at 14:16
  • If you are planning to do a lot of work that involves multithreading, I would suggest to invest a few days and study it systematically. It will save you a lot of frustration down the road. Here is a good online resource: [Threading in C#](http://www.albahari.com/threading/) by ​Joseph Albahari. If you prefer learning from books, Stephen Cleary's [Concurrency in C#](https://www.amazon.com/Concurrency-Cookbook-Asynchronous-Multithreaded-Programming/dp/149205450X) should be quite good. I haven't read it, but the author is one of the best experts on this subject. – Theodor Zoulias Sep 20 '22 at 14:24

1 Answers1

1

You cannot update the UI from any other thread than the UI thread. There are numerous questions regarding this, for example Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on.

The guide you are following works since it is only uses the console for output, and all the methods in the Console-class are thread safe. In general, static methods should be thread safe, since they would otherwise be difficult to use in a multi threaded program. As far as I know, all static methods provided by the framework follows this guideline. But there is nothing intrinsic about static methods that make them thread safe, so be careful and read the documentation. You should also assume that non-static methods are not thread safe, unless otherwise noted.

I would recommend starting by doing a fair amount of reading about thread safety and guidelines before doing anything serious involving threads. There are lots of potential hazards, and most of them are much more difficult to debug than this one.

I would also suggest following an newer guide, creating threads manually is an outdated method, the modern way is to use tasks and async/await. This provides a much more convenient method to do some work in the background, and update the UI with the result once it is done.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • 1
    As a side note: "console based, and the console is thread safe" as in the class `Console`, which is thread safe: https://learn.microsoft.com/en-us/dotnet/api/system.console?view=net-6.0#thread-safety. The program is build as project type `Console`, which does not guarantee any thread safety. – Denxorz Sep 20 '22 at 13:42
  • *"and the console is thread safe"* -- This needs to be edited from console to [`Console`](https://learn.microsoft.com/en-us/dotnet/api/system.console). – Theodor Zoulias Sep 20 '22 at 13:45
  • *"...is by convention thread safe"* -- What is the meaning of "by convention" here? The thread safety of the `Console` class is well documented, it's not something that is coming from the collective wisdom of the .NET community. – Theodor Zoulias Sep 20 '22 at 13:48
  • @TheodorZoulias static methods provided by the framework are thread safe, at least to the best of my knowledge, if you know any counter examples I would be glad to hear them. And I would argue that any static methods *should* be thread safe. I.e. the default assumption should be that static methods are thread safe, and non static methods are not. – JonasH Sep 20 '22 at 13:58
  • Ah, now I understand what you mean. I have no counter example of a static method that is not thread safe, and I agree with your statement that static methods *should* be thread safe. But since the thread safety of the `Concole` class is a documented guarantee, I think that referring to the documentation should take precedence over referring to the convention. – Theodor Zoulias Sep 20 '22 at 14:13