× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

C# WinForms multithreading using Task Factory and updating the UI from another thread using Task Scheduler

Michael Urvan
Sep 10, 2015
<p>Below is a basic example of WinForm threading, assuming you have buttons Start and Stop that you want to launch a new thread that does some work. The example shows inline code but you would probably want to create a separate class to house your code.</p> <pre><code class="language-cs">Task task = null; CancellationTokenSource taskCancelSource = null; TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); private void btnStart_Click(object sender, RoutedEventArgs e) { btnStop.IsEnabled = true; btnStart.IsEnabled = false; if (task != null) task.Dispose(); if (taskCancelSource != null) taskCancelSource.Dispose(); taskCancelSource = new CancellationTokenSource(); CancellationToken taskToken = taskCancelSource.Token; task = Task.Factory.StartNew(() =&gt; { int count = 0; while(!taskToken.IsCancellationRequested) { using(WebClient web = new WebClient()) { string url = "http://www.codementor.io"; { byte[] buffer = new byte[8192]; using(Stream s = web.OpenRead(url)) { int r = s.Read(buffer, 0, R.Next(128, 8191)); string str = System.Text.Encoding.UTF8.GetString(buffer, 0 , buffer.Length &gt; 40 ? 40 : buffer.Length); Task.Factory.StartNew(() =&gt; { txtLog.AppendText(String.Format("{0} {1} {2}\r\n", count, url, str)); txtLog.ScrollToEnd(); }, CancellationToken.None, TaskCreationOptions.None, uiScheduler); } } } count++; if (!taskToken.IsCancellationRequested) Thread.Sleep(5000); } }); } void StopThread() { if (taskCancelSource != null) taskCancelSource.Cancel(); if (task != null) task.Wait(); } private void btnStop_Click(object sender, RoutedEventArgs e) { btnStart.IsEnabled = true; btnStop.IsEnabled = false; StopThread(); } private void Window_Closing(object sender, CancelEventArgs e) { StopThread(); } </code></pre> <p>As a general rule, you would not want the other thread to access UI elements but this is a common example of a loggin textbox that you want to write strings to. In WPF you would have a public property on the form class and updating the property would update the textbox by itself (a better implementation), but in WinForms you won't have that design so you might update it directly. In the above example, you would add our uiScheduler variable passed as a parameter to a call to Task.Factory.StartNew - this is required to access the UI.</p> <p> </p> <p>The code within the lambda expression will run in the threading context of the UI and current object context, so we can access variables as well as update the UI directly:</p> <pre><code class="language-cs">Task.Factory.StartNew(() =&gt; { txtLog.AppendText(String.Format("{0} {1} {2}\r\n", count, url, str)); txtLog.ScrollToEnd(); }, CancellationToken.None, TaskCreationOptions.None, uiScheduler); </code></pre> <p> </p> <p> </p>
comments powered by Disqus