{"id":455,"date":"2010-06-11T11:59:50","date_gmt":"2010-06-11T11:59:50","guid":{"rendered":"http:\/\/dirk.forbiddendream.be\/?p=455"},"modified":"2016-01-07T10:49:23","modified_gmt":"2016-01-07T10:49:23","slug":"cross-threading-operations-in-net-c-vb","status":"publish","type":"post","link":"https:\/\/dirk.schuermans.me\/?p=455","title":{"rendered":"Cross-threading operations in .NET (C# \/ VB)"},"content":{"rendered":"<p>Hello everyone,<\/p>\n<p>Recently I was asked in class how to solve the whole &#8220;Unable to access control created on another thread&#8221; exception.<br \/>\nThe teachers apperantly didn&#8217;t know the solution so my classmates turned to me.<\/p>\n<p>It&#8217;s pretty simple actually.<br \/>\nWhat we basicly have to do, is <strong>delegate<\/strong> the task.<\/p>\n<p><!--more--><\/p>\n<p>Let&#8217;s say we have 2 threads.<\/p>\n<p>The main thread being our application when it starts, and a worker thread that&#8217;s created when we press a button.<br \/>\nWhen the worker thread has been started, we want it to update a TextBox value and increment it by 1.<\/p>\n<p>Now, if we do not delegate this task to the main thread when it&#8217;s being called from the worker thread, it will raise an exception saying it can&#8217;t access controls created by \/ on a different thread.<\/p>\n<p>So the only thing we have to do, is create a delegate for this:<\/p>\n<p><strong>VB.NET:<\/strong><\/p>\n<pre name=\"code\" class=\"vb.net\">'Delegate\r\nPrivate Delegate Sub MyDelegate()<\/pre>\n<p><em>How to declare a delegate in VB.NET<\/em><\/p>\n<p><strong>C#.NET<\/strong><\/p>\n<pre name=\"code\" class=\"c-sharp\">\/\/ Delegate\r\npublic delegate void MyDelegate();<\/pre>\n<p><em>How to declare a delegate in C#.NET<\/em><\/p>\n<p>That&#8217;s about it when it comes down to actually <strong>creating<\/strong> the delegates.<br \/>\nNow it&#8217;s time to use them.<\/p>\n<p>So we will create a new thread when we click a button, and that thread will execute a method called &#8220;DoIncrement()&#8221;<br \/>\nThis method will loop untill our counter is 10 and it will sleep for 1000 miliseconds (= 1 second) after it has incremented the value.<br \/>\nOnce the counter has been incremented, a method called &#8220;ShowValue()&#8221; will be called to display the current value in a TextBox<\/p>\n<p><strong>VB.NET:<\/strong><\/p>\n<pre name=\"code\" class=\"vb.net\">Private Sub DoIncrement()\r\n\tWhile (Me.m_nCounter &lt; 10)\r\n\t\t'Increment the counter\r\n\t\tMe.m_nCounter += 1\r\n\t\tMe.ShowValue()\r\n\r\n\t\t'Let the worker thread sleep\r\n\t\tThread.Sleep(1000)\r\n\tEnd While\r\n\r\n\tMe.m_nCounter = 0\r\n\tMessageBox.Show(\"Worker thread is done!\")\r\nEnd Sub<\/pre>\n<p><em>The DoIncrement() procedure in VB.NET<\/em><\/p>\n<p><strong>C#.NET<\/strong><\/p>\n<pre name=\"code\" class=\"c-sharp\">\/\/\/\r\n\r\n\/\/\/ Increments the counter by 1\r\n\/\/\/ \r\n\r\nprivate void DoIncrement()\r\n{\r\n\twhile (m_nCounter &lt; 10)\r\n\t{\r\n\t\t\/\/ Increment the counter\r\n\t\tthis.m_nCounter++;\r\n\t\tthis.ShowValue();\r\n\r\n\t\t\/\/ Pause the worker thread for 1 second\r\n\t\tThread.Sleep(1000);\r\n\t}\r\n\r\n\tthis.m_nCounter = 0;\r\n\tMessageBox.Show(\"Worker thread has finished!\");\r\n}<\/pre>\n<p><em>The DoIncrement() procedure in C#.NET<\/em><\/p>\n<p>Now, in the &#8220;ShowValue()&#8221; method we will call upon the delegate we&#8217;ve declared.<br \/>\nWhat we&#8217;ll do is check if the TextBox we&#8217;re trying to show the value in belongs to another thread and if it does, delegate the task &#8220;ShowValue&#8221; to the thread that owns the control.<\/p>\n<p><strong>VB.NET:<\/strong><\/p>\n<pre name=\"code\" class=\"vb.net\">Private Sub ShowValue()\r\n\tIf (Me.txtValue.InvokeRequired) Then\r\n\t\t'Declare a new instance of our delegate\r\n\t\tDim Show As MyDelegate\r\n\r\n\t\t'Setup the delegate\r\n\t\tShow = AddressOf ShowValue\r\n\r\n\t\t'Invoke the delegate for the control\r\n\t\tMe.txtValue.Invoke(Show)\r\n\tElse\r\n\t\t'Update the value of the textbox\r\n\t\ttxtValue.Text = m_nCounter.ToString()\r\n\tEnd If\r\nEnd Sub<\/pre>\n<p><em>The ShowValue() procedure in VB.NET<\/em><\/p>\n<p><strong>C#.NET:<\/strong><\/p>\n<pre name=\"code\" class=\"c-sharp\">\/\/\/\r\n\r\n\/\/\/ Shows the current value of m_nCounter in txtValue\r\n\/\/\/ \r\n\r\nprivate void ShowValue()\r\n{\r\n\t\/\/ Check to which thread the control belongs\r\n\tif (this.txtValue.InvokeRequired)\r\n\t{\r\n\t\t\/\/ Fire the delegate\r\n\t\tthis.txtValue.Invoke(new MyDelegate(ShowValue));\r\n\t}\r\n\telse\r\n\t{\r\n\t\t\/\/ Show the current value\r\n\t\tthis.txtValue.Text = this.m_nCounter.ToString();\r\n\t}\r\n}<\/pre>\n<p><em>The ShowValue() procedure in C#.NET<\/em><\/p>\n<p>Here is the complete source code for the VB.NET and C#.NET projects.<br \/>\nAll you need is a small form with 1 button called <strong>btnStart<\/strong> and a TextBox called <strong>txtValue<\/strong><\/p>\n<p><strong>VB.NET<\/strong><\/p>\n<pre name=\"code\" class=\"vb.net\">Imports System.Threading\r\n\r\nPublic Class Form1\r\n\r\n    'Delegate\r\n    Private Delegate Sub MyDelegate()\r\n\r\n    'Variables\r\n    Private m_nCounter As Integer\r\n    Private m_trdCounter As Thread\r\n\r\n    '''\r\n\r\n    ''' Occurs when the user clicks the start button\r\n    ''' \r\n\r\n    '''\r\nSystem.Object : The object calling this procedure\r\n    '''\r\nSystem.EventArgs : The event arguments\r\n    ''' \r\n    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click\r\n        'Setup the thread\r\n        Me.m_trdCounter = New Thread(AddressOf Me.DoIncrement)\r\n        Me.m_trdCounter.IsBackground = True\r\n\r\n        'Start the new thread\r\n        Me.m_trdCounter.Start()\r\n    End Sub\r\n\r\n    '''\r\n\r\n    ''' Increment the value of m_nCounter by 1 and call ShowValue()\r\n    ''' \r\n\r\n    ''' \r\n    Private Sub DoIncrement()\r\n        While (Me.m_nCounter &lt; 10)\r\n            'Increment the counter\r\n            Me.m_nCounter += 1\r\n            Me.ShowValue()\r\n\r\n            'Let the worker thread sleep\r\n            Thread.Sleep(1000)\r\n        End While\r\n\r\n        Me.m_nCounter = 0\r\n        MessageBox.Show(\"Worker thread is done!\")\r\n    End Sub\r\n\r\n    '''\r\n\r\n    ''' Show the current value of m_nCounter in the TextBox\r\n    ''' \r\n\r\n    ''' \r\n    Private Sub ShowValue()\r\n        If (Me.txtValue.InvokeRequired) Then\r\n            'Declare a new instance of our delegate\r\n            Dim Show As MyDelegate\r\n\r\n            'Setup the delegate\r\n            Show = AddressOf ShowValue\r\n\r\n            'Invoke the delegate for the control\r\n            Me.txtValue.Invoke(Show)\r\n        Else\r\n            'Update the value of the textbox\r\n            txtValue.Text = m_nCounter.ToString()\r\n        End If\r\n    End Sub\r\nEnd Class<\/pre>\n<p><em>The source code in VB.NET<\/em><\/p>\n<p><strong>C#.NET<\/strong><\/p>\n<pre name=\"code\" class=\"c-sharp\">using System;\r\nusing System.Collections.Generic;\r\nusing System.ComponentModel;\r\nusing System.Data;\r\nusing System.Drawing;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Windows.Forms;\r\nusing System.Threading;\r\n\r\nnamespace Crossthreading_Example\r\n{\r\n    \/\/ Delegate\r\n    public delegate void MyDelegate();\r\n\r\n    public partial class Form1 : Form\r\n    {\r\n        \/\/ Variables\r\n        private int m_nCounter;\r\n        private Thread m_trdCounter;\r\n\r\n        \/\/\/\r\n\r\n        \/\/\/ Default constructor\r\n        \/\/\/ \r\n\r\n        public Form1()\r\n        {\r\n            InitializeComponent();\r\n\r\n            \/\/ Initialize\r\n            m_nCounter = 0;\r\n        }\r\n\r\n        \/\/\/\r\n\r\n        \/\/\/ Occurs when the user clicks the start button\r\n        \/\/\/ \r\n\r\n        \/\/\/\r\nSystem.Object : The object calling this method\r\n        \/\/\/\r\nSystem.EventArgs : The event arguments\r\n        private void btnStart_Click(object sender, EventArgs e)\r\n        {\r\n            \/\/ Setup a new thread\r\n            this.m_trdCounter = new Thread(DoIncrement);\r\n            this.m_trdCounter.IsBackground = true;\r\n\r\n            \/\/ Start the thread\r\n            this.m_trdCounter.Start();\r\n        }\r\n\r\n        \/\/\/\r\n\r\n        \/\/\/ Increments the counter by 1\r\n        \/\/\/ \r\n\r\n        private void DoIncrement()\r\n        {\r\n            while (m_nCounter &lt; 10)\r\n            {\r\n                \/\/ Increment the counter\r\n                this.m_nCounter++;\r\n                this.ShowValue();\r\n\r\n                \/\/ Pause the worker thread for 1 second\r\n                Thread.Sleep(1000);\r\n            }\r\n\r\n            this.m_nCounter = 0;\r\n            MessageBox.Show(\"Worker thread has finished!\");\r\n        }\r\n\r\n        \/\/\/\r\n\r\n        \/\/\/ Shows the current value of m_nCounter in txtValue\r\n        \/\/\/ \r\n\r\n        private void ShowValue()\r\n        {\r\n            \/\/ Check to which thread the control belongs\r\n            if (this.txtValue.InvokeRequired)\r\n            {\r\n                \/\/ Fire the delegate\r\n                this.txtValue.Invoke(new MyDelegate(ShowValue));\r\n            }\r\n            else\r\n            {\r\n                \/\/ Show the current value\r\n                this.txtValue.Text = this.m_nCounter.ToString();\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p><em>The source code in C#<\/em><\/p>\n<p>There you go, access controls from other threads ;P<\/p>\n<p>If you have any questions regarding this topic, feel free to ask and I&#8217;ll do my best to answer them.<\/p>\n<p>Happy coding!<\/p>\n<p>&#8211; Dirk<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello everyone, Recently I was asked in class how to solve the whole &#8220;Unable to access control created on another thread&#8221; exception. The teachers apperantly didn&#8217;t know the solution so my classmates turned to me. It&#8217;s pretty simple actually. What we basicly have to do, is delegate the task.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[38],"tags":[],"_links":{"self":[{"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=\/wp\/v2\/posts\/455"}],"collection":[{"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=455"}],"version-history":[{"count":6,"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=\/wp\/v2\/posts\/455\/revisions"}],"predecessor-version":[{"id":776,"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=\/wp\/v2\/posts\/455\/revisions\/776"}],"wp:attachment":[{"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=455"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=455"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dirk.schuermans.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=455"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}