Reputation: 21
i have written code to repeat a calculation till it finds the largest number a datatype can hold using this code
int a = 0;
int b = 1;
int c = 0;
for (int j = 0; j < 10000; j++)
{
c = a + b;
txtOutput.Text = c.ToString();
a = b;
b = c;
}
How would i use the task class or parallelism to make this faster as currently it takes almost 20 minutes to complete this calculation, i need it to happen in 1 minute or less, i tried this code
Parallel.For(0, 1000000, i =>
{
for (int j = 0; j < 10000; j++)
{
c = a + b;
txtOutput.Text = c.ToString();
a = b;
b = c;
}
});
But it still takes the same amount of time, i am doing this to learn about multi threading loops for an upcoming project
Upvotes: 0
Views: 776
Reputation: 29274
Just move the textbox updating outside the loop
public long SerialCalc(int n)
{
long a = 0, b = 1, c = 0;
for (int j = 0; j < n; j++)
{
c = a + b;
a = b;
b = c;
}
return c;
}
and then call it with
private void button1_Click(object sender, EventArgs e)
{
if (int.TryParse(textBox1.Text, out int n) && n>=0)
{
textBox2.Clear();
textBox2.Text = SerialCalc(n).ToString();
}
}
This would make it so much faster. In fact your code overflows long
several times as it goes past long.MaxValue
, becomes negative, goes through zero and past long.MaxValue
over and over again.
With a value of 1000000
it takes less than 1 second to finish.
Upvotes: 0
Reputation: 1389
Short answer, you can't. Each calculation uses the results of the previous, which means no calculation can start until the previous has finished - your algorithm is synchronous by design. Before you can even try running asynchronously/multithreaded, you need to break up the algorithm into independent segments which you then combine at the end. (note, there are easier ways to boost your performance, not hammering the textbox every iteration is a good start as others have commented). Below is a short example of how you could run an algorithm asyncronously.
Once you have the algorithm broken up into independent segments, you can run it in async mode with Task.Run
public async Task<ResultType> RunAlgorithm(){
foreach(var segment in GetSegments()){
//start processing each segment
resultTaskList.Add(Task.Run(ProcessSegment(segment)));
}
foreach(var resultTask in resultTaskList)
resultList.Add(await resultTask); //wait for each task to finish processing
var result = CombineResults(resultList);//combine results to one final result
return result;
}
public ResultType ProcessSegment(SegmentType segment){
//sync code here
}
public List<SegmentType> GetSegments(){
//break your sample/input data into smaller segments to be processed in parallel
}
public ResultType CombineResults(List<ResultType>){
//take the results of each set of calculations and come up with the overall/total/combined answer
}
The above code is a fairly minimal example for parallelising a task. its up to you to define a sensible definition for the 'GetSegments' method, the 'ProcessSegment' method and the 'CombineResults' method.
Note, you will threadstarve yourself if you start too many tasks. You can either tune getSegments to return X segments where X is your threadcount. Or you can set it to only run X tasks at a time using some fancy Task.WhenAny calls. I'll give an example of the latter later.
You might also want to make the method signatures very different depending on what works best for your code, this is just a stubbed out example.
Upvotes: 0
Reputation: 435
As The General said, if you touch the UI, you will move your application into a single threaded one.
But there is a thing I don't understand: why do you have to change the content of a text box for each computation? I'm quite sure the data will change so fast that the user won't understand what is happening.
I suggest you to change your code in this way:
Let us know if it will help you.
Upvotes: 1