Updating UI from Task
-
Hi All, In a tutorial I found a a new way (new for me)of updating a control from a thread. In the example code the new way(AsyncParallel) is in button1_Click and what I am familiar with is in button2_Click. They both do the job, but what is better, regarding performance and especially when more tasks are running that might update UI-thread? Here is the example:
namespace Task_Compare
{
public partial class Form1 : Form
{public Form1() { InitializeComponent(); } private void button1\_Click(object sender, EventArgs e) { string data = ""; Task Tf1 = Task.Factory.StartNew(() => { data = GetData(); }); Task T2 = Tf1.ContinueWith((previousTask) => { listBox1.Items.Insert(0, data); }, TaskScheduler.FromCurrentSynchronizationContext()); } private void button2\_Click(object sender, EventArgs e) { string data = ""; Task Tf2 = Task.Factory.StartNew(() => { data = GetData(); }); Tf2.Wait(); listBox1.Invoke(new EventHandler(delegate { listBox1.Items.Insert(0, data); })); } private string GetData() { string temp = ""; { temp = " Do something long running ......"; } return temp; } }
}
Groover,
0200 A9 23 0202 8D 01 80 0205 00
-
Hi All, In a tutorial I found a a new way (new for me)of updating a control from a thread. In the example code the new way(AsyncParallel) is in button1_Click and what I am familiar with is in button2_Click. They both do the job, but what is better, regarding performance and especially when more tasks are running that might update UI-thread? Here is the example:
namespace Task_Compare
{
public partial class Form1 : Form
{public Form1() { InitializeComponent(); } private void button1\_Click(object sender, EventArgs e) { string data = ""; Task Tf1 = Task.Factory.StartNew(() => { data = GetData(); }); Task T2 = Tf1.ContinueWith((previousTask) => { listBox1.Items.Insert(0, data); }, TaskScheduler.FromCurrentSynchronizationContext()); } private void button2\_Click(object sender, EventArgs e) { string data = ""; Task Tf2 = Task.Factory.StartNew(() => { data = GetData(); }); Tf2.Wait(); listBox1.Invoke(new EventHandler(delegate { listBox1.Items.Insert(0, data); })); } private string GetData() { string temp = ""; { temp = " Do something long running ......"; } return temp; } }
}
Groover,
0200 A9 23 0202 8D 01 80 0205 00
GrooverFromHolland wrote:
They both do the job, but what is better
They do the same; which one is 'better' is nitpicking. If you want to pick the nits (which can be fun and educational), download ILspy and decompile the class. The Invoke-pattern is older than the Task-class, which was added in 4 (?). To some, the newer way is "more readable" as it does the same with less code (=fewer bugs). Others will be used to the old pattern. I prefer not to have a wait or an extra task, but to invoke the UI from the thread using the classical invoke-pattern from MSDN;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;namespace ConsoleApplication2
{
class Program
{
static void Main()
{
System.Threading.Thread.CurrentThread.Name = "Main thread";
using (var f = new SomeForm())
f.ShowDialog();
}
}
class SomeDataCollection : List { }
class SomeForm: Form
{
ListBox _listBox1;
Button _button1;
public SomeForm()
{
_listBox1 = new ListBox() { Dock = DockStyle.Fill };
_button1 = new Button() { Dock = DockStyle.Top };
Controls.AddRange(new Control[] { _listBox1, _button1 });\_button1.Click += delegate { Task Tf2 = Task.Factory.StartNew(() => { SomeDataCollection \_data = getData(); showData(\_data); }); }; } void showData(IList whatData) { if (InvokeRequired) { Invoke(new Action(showData), new\[\] { whatData }); return; } \_listBox1.DataSource = whatData; } SomeDataCollection getData() { var result = new SomeDataCollection(); for (int i = 0; i < 10; i++) { result.Add(Guid.NewGuid()); System.Threading.Thread.Sleep(150); } return result; } }
}
I keep preferring the old style as it makes for very predictable code-constructs. I would however add that it's beneficial during debugging to name each thread during coding! Put a breakpoint on line 35, run, and when
-
GrooverFromHolland wrote:
They both do the job, but what is better
They do the same; which one is 'better' is nitpicking. If you want to pick the nits (which can be fun and educational), download ILspy and decompile the class. The Invoke-pattern is older than the Task-class, which was added in 4 (?). To some, the newer way is "more readable" as it does the same with less code (=fewer bugs). Others will be used to the old pattern. I prefer not to have a wait or an extra task, but to invoke the UI from the thread using the classical invoke-pattern from MSDN;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;namespace ConsoleApplication2
{
class Program
{
static void Main()
{
System.Threading.Thread.CurrentThread.Name = "Main thread";
using (var f = new SomeForm())
f.ShowDialog();
}
}
class SomeDataCollection : List { }
class SomeForm: Form
{
ListBox _listBox1;
Button _button1;
public SomeForm()
{
_listBox1 = new ListBox() { Dock = DockStyle.Fill };
_button1 = new Button() { Dock = DockStyle.Top };
Controls.AddRange(new Control[] { _listBox1, _button1 });\_button1.Click += delegate { Task Tf2 = Task.Factory.StartNew(() => { SomeDataCollection \_data = getData(); showData(\_data); }); }; } void showData(IList whatData) { if (InvokeRequired) { Invoke(new Action(showData), new\[\] { whatData }); return; } \_listBox1.DataSource = whatData; } SomeDataCollection getData() { var result = new SomeDataCollection(); for (int i = 0; i < 10; i++) { result.Add(Guid.NewGuid()); System.Threading.Thread.Sleep(150); } return result; } }
}
I keep preferring the old style as it makes for very predictable code-constructs. I would however add that it's beneficial during debugging to name each thread during coding! Put a breakpoint on line 35, run, and when
Hi Eddy, Thank You for the good explanation. Regards, Groover
0200 A9 23 0202 8D 01 80 0205 00
-
Hi Eddy, Thank You for the good explanation. Regards, Groover
0200 A9 23 0202 8D 01 80 0205 00