{"id":136,"date":"2016-11-15T15:08:43","date_gmt":"2016-11-15T13:08:43","guid":{"rendered":"http:\/\/carsten.familie-schumann.info\/blog\/?page_id=136"},"modified":"2016-11-15T15:08:43","modified_gmt":"2016-11-15T13:08:43","slug":"einfaches-invoke-in-c","status":"publish","type":"page","link":"https:\/\/carsten.familie-schumann.info\/blog\/einfaches-invoke-in-c\/","title":{"rendered":"Einfaches Invoke in C#"},"content":{"rendered":"<p><img decoding=\"async\" class=\"alignright \" src=\"http:\/\/carsten.familie-schumann.info\/blog\/wp-content\/uploads\/2016\/11\/invalidoperation.png\" alt=\"invalidoperation\" \/>Wer kennt sie nicht&#8230;. die ber\u00fchmt-ber\u00fcchtigte &#8222;Ung\u00fcltiger thread\u00fcbergreifender Vorgang&#8220; in C#? Sie tritt typischerweise dann auf, wenn man von einem BackgroundWorker oder einem Thread auf Elemente\u00a0 der Oberfl\u00e4che zugreifen m\u00f6chte. Im Netz gibt es hierzu ziemlich viele Anleitungen, beispielsweise die von Microsoft auf <a href=\"https:\/\/msdn.microsoft.com\/de-de\/library\/ms171728(v=vs.110).aspx\">https:\/\/msdn.microsoft.com\/de-de\/library\/ms171728(v=vs.110).aspx<\/a>. Diese L\u00f6sungen haben eins gemeinsam: Sie sind h\u00e4ufig schwer lesbar und klobig.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate void SetText(string text)\r\n{\r\n\t\/\/ InvokeRequired required compares the thread ID of the\r\n\t\/\/ calling thread to the thread ID of the creating thread.\r\n\t\/\/ If these threads are different, it returns true.\r\n\tif (this.textBox1.InvokeRequired)\r\n\t{\t\r\n\t\tSetTextCallback d = new SetTextCallback(SetText);\r\n\t\tthis.Invoke(d, new object&#x5B;] { text });\r\n\t}\r\n\telse\r\n\t{\r\n\t\tthis.textBox1.Text = text;\r\n\t}\r\n}\r\n<\/pre>\n<p>Den Schabernack kann man aber relativ einfach umgehen. Daf\u00fcr kann man seit .NET 4.0 ein sogenanntes Mixin verwenden, das man irgendwo in seinem Projekt ablegt:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static class FormInvokeExtension\r\n{\r\n    static public void UIThreadAsync(this Control control, Action code)\r\n    {\r\n        if (control.InvokeRequired)\r\n        {\r\n            control.BeginInvoke(code);\r\n            return;\r\n        }\r\n        code.Invoke();\r\n    }\r\n\r\n    static public void UIThreadSync(this Control control, Action code)\r\n    {\r\n        if (control.InvokeRequired)\r\n        {\r\n            control.Invoke(code);\r\n            return;\r\n        }\r\n        code.Invoke();\r\n    }\r\n}\r\n<\/pre>\n<p>Diese Klasse erweitert S\u00c4MTLICHE Controls um die Funktionen UIThreadAsync und UIThreadSync. Wie der Name schon sagt, wird hiermit entweder synchron oder asynchron ein Codeschnipsel im Context des UI-Thread ausgef\u00fchrt:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate void SetText(string text)\r\n{\r\n    this.UIThreadAsync(delegate\r\n    {\r\n        this.textBox1.Text = text;\r\n    });\r\n}\r\n<\/pre>\n<p>Praktischerweise l\u00e4sst sich das sogar mit LINQ kombinieren:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    ...\r\n    this.UIThreadSync(()=&gt; control3.setText(param1, param2, param3));\r\n    ...\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Wer kennt sie nicht&#8230;. die ber\u00fchmt-ber\u00fcchtigte &#8222;Ung\u00fcltiger thread\u00fcbergreifender Vorgang&#8220; in C#? Sie tritt typischerweise dann auf, wenn man von einem BackgroundWorker oder einem Thread auf Elemente\u00a0 der Oberfl\u00e4che zugreifen m\u00f6chte. Im Netz gibt es hierzu ziemlich viele Anleitungen, beispielsweise die von Microsoft auf https:\/\/msdn.microsoft.com\/de-de\/library\/ms171728(v=vs.110).aspx. Diese L\u00f6sungen haben eins gemeinsam: Sie sind h\u00e4ufig schwer lesbar und&#8230;<br \/><a class=\"read-more-button\" href=\"https:\/\/carsten.familie-schumann.info\/blog\/einfaches-invoke-in-c\/\">Mehr Lesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-136","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages\/136","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/comments?post=136"}],"version-history":[{"count":7,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages\/136\/revisions"}],"predecessor-version":[{"id":144,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages\/136\/revisions\/144"}],"wp:attachment":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/media?parent=136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}