Thursday, February 12, 2015
Task With A Return Value
namespace TasksThatReturnAValue
{
public partial class Form1 : Form
{
//Use the Task<TResult> class to represent an asynchronous method that returns a value
//Use the Func<..TResult> delegate with the Task<TResult> class
Random rand = new Random();
public Form1()
{
InitializeComponent();
}
//Not a good way, but to know the difference
private void btnStartTask1_Click(object sender, EventArgs e)
{
//Create a Func<> delegate
Func<long> function = ComputeTotalOfRandomNumbers;
//create a Task
Task<long> task1 = new Task<long>(function);
//start task1
task1.Start();
//get the returned value for the Task Result Property
long total = task1.Result;
//But the disadventage of doing this way is
//result property will block/waits until the result is returned
//from the asynchronous method / until task1 completes
//Since the task1.Result runs on the main thread, it will lock the UI
//display
richTextBox1.AppendText("Total of a list of randoms is: \n" + total + "\n");
}
private long ComputeTotalOfRandomNumbers()
{
int counter = 0;
long sum = 0;
do
{
int num = rand.Next();
if (num % 2 != 0)
{
sum += num;
counter++;
}
} while (counter < 1000000);
return sum;
}
private void btnStartTask2WithoutLockingUI_Click(object sender, EventArgs e)
{
//Need to take the statement Task1.Result from the main thread and put it in another task
//but the second task can only start when the first one complete
//task1 is ready to be passed to task2
//Start task1 same way as the previous
//Create a Func<> delegate
Func<long> function = ComputeTotalOfRandomNumbers;
//create a Task
Task<long> task1 = new Task<long>(function);
//start task1
task1.Start();
//Create a second task that starts or continues when the first one completes
//The Task<TResult> class defines the method ContinueWith that creates and starts
//a second task when the first one completes
//Use: public Task ContinueWith(Action<Task> continuationAction)
//so the Action<Task> represents a method (as a callback method that takes a Task as a
//parameter. You could define such method or use a Lambda expression
Action<Task<long>> action = delegate(Task<long> t)//Task represents the completed task, task1
{
//get the return value]
long total = t.Result;
//display it// apply the cross threading calls.
SetText(total.ToString(), richTextBox1);
};
//or
//Action<Task<long>> action1 = t =>
//{
// long total1 = t.Result;
// SetText(total1.ToString(), richTextBox1);
//};
Task task2 = task1.ContinueWith(action);
}
//1. define a delegate with same signature as the crosss-threading handling
// method (the SetText method)
private delegate void RichTextBoxHandler(string s, RichTextBox rtb);
private void SetText(string s, RichTextBox rtb)
{
if (rtb.InvokeRequired)
{
//create a delegate object
RichTextBoxHandler handler = SetText;
Invoke(handler, s, rtb);
}
else
{
rtb.AppendText(s + "\n");
//scroll down
rtb.ScrollToCaret();
}
}
}
}
//Lab assignment:
//===============
//Use the same idea, but this time the method ComputeTotal... should take an int parameter
//that indicates the number of odd to add.
//Start such method in a task use the continueWith to display its return value in a second task
Labels:
C#Advance
Subscribe to:
Post Comments (Atom)

No comments:
Post a Comment