{"id":1678,"date":"2014-12-10T14:00:30","date_gmt":"2014-12-10T04:00:30","guid":{"rendered":"http:\/\/www.malcolmgroves.com\/blog\/?p=1678"},"modified":"2014-12-11T10:33:18","modified_gmt":"2014-12-10T23:33:18","slug":"updating-the-ui-from-a-task","status":"publish","type":"post","link":"http:\/\/www.malcolmgroves.com\/blog\/?p=1678","title":{"rendered":"Updating the UI from a Task"},"content":{"rendered":"<p>While we&#8217;re talking things Parallel, the other part of the same demo from last post showed spawning a single task that slept for awhile and then called ShowMessage.<\/p>\n<pre>procedure TFormThreading.Button1Click(Sender: TObject);\r\nvar\r\n  aTask: ITask;\r\n  begin\r\n    \/\/ not a thread safe snippet\r\n    aTask := TTask.Create(procedure\r\n                          begin\r\n                            sleep(3000); \r\n                            ShowMessage('Hello');\r\n                          end);\r\n    aTask.Start;\r\n end;<\/pre>\n<p>Note the comment.<!--more--><\/p>\n<p>The non-threadsafe part is the call to ShowMessage. Any update of the UI should be done from the main thread.<\/p>\n<p>The quite reasonable question that followed after showing the code was &#8220;How would you make it threadsafe?&#8221;<\/p>\n<p>The correct but not very useful answer is to do the call to ShowMessage from the main thread.<\/p>\n<div id=\"attachment_1745\" style=\"width: 410px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/12\/multithreadedtheorypractice.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1745\" class=\"size-full wp-image-1745\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/12\/multithreadedtheorypractice.jpg\" alt=\"Multi-threaded Programming. Theory vs Practice\" width=\"400\" height=\"196\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/12\/multithreadedtheorypractice.jpg 400w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/12\/multithreadedtheorypractice-300x147.jpg 300w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/12\/multithreadedtheorypractice-150x73.jpg 150w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/a><p id=\"caption-attachment-1745\" class=\"wp-caption-text\">Multi-threaded Programming. Theory vs Practice<\/p><\/div>\n<p>How? You have two main choices.<\/p>\n<p>Both involve wrapping your UI code up in an anonymous method. If you pass that\u00a0method to <a href=\"http:\/\/docwiki.embarcadero.com\/Libraries\/en\/System.Classes.TThread.Synchronize\" target=\"_blank\">TThread.Synchronize<\/a>, it will be executed on the main thread and your task will block until it is finished.<\/p>\n<pre>procedure TFormThreading.Button1Click(Sender: TObject);\r\nvar\r\n  aTask: ITask;\r\nbegin\r\n  aTask := TTask.Create(procedure\r\n                        begin\r\n                          sleep (5000);\r\n                          TThread.Synchronize(nil,\r\n                                              procedure\r\n                                              begin\r\n                                                ShowMessage ('Hello');\r\n                                              end);\r\n                        end);\r\n  aTask.Start;\r\nend;<\/pre>\n<p>If instead you pass it to <a href=\"http:\/\/docwiki.embarcadero.com\/Libraries\/en\/System.Classes.TThread.Queue\" target=\"_blank\">TThread.Queue<\/a>, your Task will continue on running (or in this case, finish, as it is all done), and at some point in the future your anonymous method will execute on the main thread.<\/p>\n<pre>procedure TFormThreading.Button1Click(Sender: TObject);\r\nvar\r\n  aTask: ITask;\r\nbegin\r\n  aTask := TTask.Create(procedure\r\n                        begin\r\n                          sleep (5000);\r\n                          TThread.Queue(nil,\r\n                                        procedure\r\n                                        begin\r\n                                          ShowMessage ('Hello');\r\n                                        end);\r\n                        end);\r\n  aTask.Start;\r\nend;<\/pre>\n<p>Which one you choose will be dependent on what you are doing. In general if I can avoid blocking I will, so if my situation allows it I use Queue for performance reasons.<\/p>\n<p>If you&#8217;re looking for more details on the PPL, including some meatier examples, check out <a href=\"http:\/\/dannywind.nl\/\" target=\"_blank\">Danny Wind<\/a>&#8216;s CodeRage 9 session, and stay all the way to the end.<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"\/\/www.youtube.com\/embed\/rZfux4by0po?list=PLwUPJvR9mZHhgQYWWgF6BCkgDwIpP78ZV\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>While we&#8217;re talking things Parallel, the other part of the same demo from last post showed spawning a single task that slept for awhile and then called ShowMessage. procedure TFormThreading.Button1Click(Sender: TObject); var aTask: ITask; begin \/\/ not a thread safe snippet aTask := TTask.Create(procedure begin sleep(3000); ShowMessage(&#8216;Hello&#8217;); end); aTask.Start; end; Note the comment.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[98,123],"tags":[48,109],"class_list":["post-1678","post","type-post","status-publish","format-standard","hentry","category-coding","category-parallel","tag-embarcadero","tag-parallel"],"_links":{"self":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1678","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1678"}],"version-history":[{"count":11,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1678\/revisions"}],"predecessor-version":[{"id":1747,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1678\/revisions\/1747"}],"wp:attachment":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1678"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1678"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1678"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}