2

My knowledge was that accessing UI control will throw exception if it is accessed from the thread that is not the thread that created it (UI thread).

I got a code that does not throw exception when accessing simple properties of the UI control when run in Visual Studio with debugger.

            var name = comboBox1.Name;
            var m1 = comboBox1.Items[1].ToString();

It does when accessing SelectedIndex of the ComboBox.

            comboBox1.SelectedItem.ToString();

The same code run without debugger does not throw exception? The same behavior is when double clicking on the exe, no exception?

Why there is only exception when code is run with debugger attached and not when running without debugger (Ctrl + F5) ?

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        comboBox1.Items.Add("one");
        comboBox1.Items.Add("two");
        comboBox1.Items.Add("three");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Task.Factory.StartNew(() =>
        {
            var name = comboBox1.Name;
            var m1 = comboBox1.Items[1].ToString();

            MessageBox.Show(comboBox1.SelectedItem.ToString(), "MM");
        });
    }
}
user007
  • 1,122
  • 1
  • 10
  • 30
  • 1
    You shouldn't interact with gui controls from a different thread. Look at the related links on the right --> – LarsTech Jan 12 '16 at 17:38
  • I know I agree with you and that was my understanding. I don't understand why is it working? I was expecting exception? So if I debug in VS it will fail as expected. When I do build and give it to the client it will work, without exception??? – user007 Jan 12 '16 at 17:42
  • Can you make absolutley sure that the exception doesn't occur by wrapping the code inside `StartNew()` in a `try-catch` and opening a `MessageBox` on an exception? Otherwise you might have gotten lucky with the thread creation. – Maximilian Gerhardt Jan 12 '16 at 17:44
  • It doesn't matter if it sometimes works or not, you don't send code to a client like that. Just do it the right way. Maybe the ComboBox doesn't have a selected item. – LarsTech Jan 12 '16 at 17:45
  • I agree with everyone else, don't do it, but it's an interesting question none-the-less. :) – CodingGorilla Jan 12 '16 at 17:47

3 Answers3

2

It happens reliably in the debugger because visual studio is "smart enough" to see the mistake and forces it to always happen in order to prevent mysterious intermittent errors at runtime. This is one of the many Managed Debug Assistants included with Visual Studio. It helps you find an intermittent error by turning it in to a consistent error.

Basically, accessing a UI control from another thread is ALWAYS the wrong thing to do, but Windows doesn't always throw an error, sometimes it continues along without any problem. The MDA is active while debugging. It specifically watches for cross thread access to the UI and makes sure that the error always happens.

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
0

You probably will eventually see an exception running outside of the debugger. Keep in mind that due to attaching breakpoints etc, the debugger can change when threads interact with each other.

It is simply a matter of probability - attaching the debugger changes the execution characteristics such that in your case, you are more likely to see the threads interact in a problematic manner. The reverse can also be true.

Especially since you are using the Task api (which doesn't necessarily spawn a new thread for every background execution) it may be possible that in most cases you don't even spawn a new thread (if you are curious how this can work, you can look at "work stealing algorithms")

Nathan
  • 10,593
  • 10
  • 63
  • 87
0

https://msdn.microsoft.com/en-us/library/ms171728.aspx

This exception occurs reliably during debugging and, under some circumstances, at run time.

So my use case is not in the: "under some circumstances, at run time"

Dharman
  • 30,962
  • 25
  • 85
  • 135
user007
  • 1,122
  • 1
  • 10
  • 30
  • 1
    It happens reliably in the debugger because visual studio is "smart enough" to see the mistake and forces it to always happen in order to prevent mysterious intermittent mysterious errors at runtime. This is one of the many `Managed Debug Assistants` included with Visual Studio. It helps you find an intermittent error by turning it in to a consistent error. – Bradley Uffner Jan 12 '16 at 17:55
  • @user007 See this thread [I can update UI from background thread, why?](http://stackoverflow.com/questions/34374045/i-can-update-ui-from-background-thread-why/34374307#34374307). Put `Control.CheckForIllegalCrossThreadCalls = true;` in your `Main` method and you'll get one and the same behavior in debugger and run time. It doesn't mean you should experiment - do not call any UI property/method from non UI thread even if it **seems** to work, – Ivan Stoev Jan 12 '16 at 19:34