Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Crossthreading work this way?

Solved

Seems that Oliver is right. After Several tries I got the exception and in debug mode i get it for sure. So this has to be all about timing. You should also check Matthew wattsons answer ;)

Example

First of all a little example that shall explain my confusion.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace testCrossThreading
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            new Thread(ThreadJob).Start();
        }

        void ThreadJob()
        {
            //label1.Text = "1";
            changeText(label1, "1");
        }

        void changeText(Label L, String message)
        {
            L.Text = message;
        }
    }
}

Question

So now my question: if I uncomment label1.Text = "1"; in the function "ThreadJob" then I get an Cross thread exception as expected. But if i leave it commented like the example shows it does work. But why? The function is called by the sub thread and I don't invoke anything. So it is still the sub Thread and not the GUI thread that changes the text of label imo. Or am I missing something?

I would write it like this.

void ThreadJob()
        {
            Action a = () => label1.Text = "1";
            this.Invoke(a);
        }
like image 638
lorenz albert Avatar asked Mar 15 '13 10:03

lorenz albert


People also ask

Why does cross threading happen?

The issue of cross threading occurs most commonly when a screw is installed at a slight angle, causing the threads of the screw to not match up correctly with those of the nut or threaded hole. This can result in the fastening jamming or becoming damaged.

How does cross threading work?

What is cross-threading? Cross-threading occurs when the first external thread crosses the internal thread in such a way that the thread contacted on one side of the internal thread is not on the same revolution as the thread contacted on the opposite side.

How do screws get cross threaded?

A cross-threaded screw occurs when the threads of a screw do not properly align with the threads in the part being fastened. Cross-threading is typically caused when the two parts being fastened together aren't properly aligned, so the holes don't match up.


2 Answers

I think it's just a timing issue. If you try to update a gui element from a non-gui thread the cross-thread exception can be thrown. You can even disable the whole cross-thread exceptions by calling

Form.CheckForIllegalCrossThreadCalls = false;

but after the exception is gone, the further behavior is undefined and can lead to very subtle bugs. So take the exception as a hint for a code smell but be aware that sometimes the exception won't be thrown even if it should be.

like image 182
Oliver Avatar answered Sep 29 '22 15:09

Oliver


I think you may have a race condition, which is why results are varying.

If you attempt to change the Text property of a control which isn't currently displayed, then .Net doesn't care which thread changes it.

In your code, you start a thread from the constructor. The code which actually displays the form may or may not have displayed it before the code in the thread that sets the property executes.

When you call an extra function to set the property, the timings change and exposes the race condition.

You could test this by adding a Thread.Sleep(100) to the start of ThreadJob().

like image 34
Matthew Watson Avatar answered Sep 29 '22 14:09

Matthew Watson