{"id":101,"date":"2010-01-26T17:00:43","date_gmt":"2010-01-26T15:00:43","guid":{"rendered":"http:\/\/www.limilabs.com\/blog\/?p=101"},"modified":"2010-01-26T17:00:43","modified_gmt":"2010-01-26T15:00:43","slug":"cross-thread-operations-with-postsharp","status":"publish","type":"post","link":"https:\/\/www.limilabs.com\/blog\/cross-thread-operations-with-postsharp","title":{"rendered":"Cross-thread operations with PostSharp"},"content":{"rendered":"<p>When you try to <strong> inform User Interface<\/strong> (UI) about the <strong>background operation progress<\/strong> or <strong>completion<\/strong>, you can not do it from the background thread.<\/p>\n<p>UI doesn&#8217;t like to be informed about anything from a different thread: you&#8217;ll get <strong>&#8220;System.InvalidOperationException: Cross-thread operation not valid: Control &#8216;xxx&#8217; accessed from a thread other than the thread it was created on.&#8221;<\/strong> exception from WinForms control, if you try:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void ShowStatus(ApplicationStatus status)\n{\n    this._lblServiceAddress.Text = &quot;Connected to: &quot;\n        + status.WebServiceAddress;\n    this._lblUserId.Text = &quot;Working as: &quot;\n        + status.UserId;\n}\n<\/pre>\n<p>The easiest sollution is to use <em>BeginInvoke <\/em>method on the control <em>Control<\/em> or <em>Form<\/em>:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void ShowStatus(ApplicationStatus status)\n{\n    this.BeginInvoke((MethodInvoker)(() =&gt;\n        {\n            this._lblServiceAddress.Text = &quot;Connected to: &quot;\n                + status.WebServiceAddress;\n            this._lblUserId.Text = &quot;Working as: &quot;\n                + status.UserId;\n        }));\n}\n<\/pre>\n<p>Well, it&#8217;s fun to write this once, but if you have many operations done in background sooner or later you&#8217;d like to have something nicer. Like an <strong>attribute<\/strong> for example:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;ThreadAccessibleUI]\npublic void ShowStatus(ApplicationStatus status)\n{\n    this._lblServiceAddress.Text = &quot;Connected to: &quot; + status.WebServiceAddress;\n    this._lblUserId.Text = &quot;Working as: &quot; + status.UserId;\n}\n<\/pre>\n<p>Here&#8217;s the attribute implementation of such attribute using PostSharp 1.5:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ PostSharp attribute.\n\/\/\/ Use it to mark Control's methods that\n\/\/\/ are invoked from background thread.\n\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;remarks&gt;\n\/\/\/ Be careful as BeginInvoke uses the message queue.\n\/\/\/ This means that the interface will be refreshed\n\/\/\/ when application has a chance to process its messages.\n\/\/\/ &lt;\/remarks&gt;\n&#x5B;AttributeUsage(AttributeTargets.Method)]\n&#x5B;Serializable] \/\/ required by PostSharp\npublic class ThreadAccessibleUIAttribute : OnMethodInvocationAspect\n{\n    public override void OnInvocation(\n        MethodInvocationEventArgs eventArgs)\n    {\n        Control control = eventArgs.Instance as Control;\n        if (control == null)\n            throw new ApplicationException(\n                &quot;ThreadAccessibleUIAttribute&quot; +\n                &quot;can be applied only to methods on Control class&quot;);\n\n        \/\/ The form may be closed before\n        \/\/ this method is called from another thread.\n        if (control.Created == false)\n            return;\n\n        control.BeginInvoke((MethodInvoker)eventArgs.Proceed);\n    }\n};\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>When you try to inform User Interface (UI) about the background operation progress or completion, you can not do it from the background thread. UI doesn&#8217;t like to be informed about anything from a different thread: you&#8217;ll get &#8220;System.InvalidOperationException: Cross-thread operation not valid: Control &#8216;xxx&#8217; accessed from a thread other than the thread it was [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[43,61],"class_list":["post-101","post","type-post","status-publish","format-standard","hentry","category-programming","tag-postsharp","tag-winforms"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/101"}],"collection":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/comments?post=101"}],"version-history":[{"count":0,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/101\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/media?parent=101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/categories?post=101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/tags?post=101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}