Multithreaded function calls
-
Assume that I have a pipe that consists of sections of variable radiuses and that I want to make calculations at different frequencies. So I want the calculations done at different threads for each frequency, but the list of pipe sections stays the same.
public class PipeSection { public PipeSection(double radius) { this.Radius = radius; } public double Radius { get; set; } public double Calculate(double Frequency) { return Frequency \* this.Radius; } }
To run the frequencies in parallel I use Rx:
CancellationTokenSource ctr = new CancellationTokenSource();
List wn = new List();public MainWindow() { InitializeComponent(); PipeSection\[\] input = { new PipeSection(5), new PipeSection(6), new PipeSection(7) }; wn.AddRange(input); //Calcualte at the frequencies 0,100,2000,3000 var FreqData = new double\[\] { 0, 100, 2000, 3000 }.ToObservable(); FreqData //Off the ui thread .ObserveOn(Scheduler.Default) //Run each thread seperatly .SelectMany(x => Task.Run(() => DoCalcualtions(x,wn), ctr.Token)) //Back to the UI thread .ObserveOnDispatcher() //Subscribe and start the calcualtions .Subscribe(args => { //Update the progressbar when a thread is completed pgbProgress.Value += 1; //Tell me what thread is completed txtText.Text += Environment.NewLine + args.ToString(); }, () => { //All done, here I could do sorting etc. txtText.Text += Environment.NewLine + "All done"; } ); } private double DoCalcualtions(double Freq, List input) { double result=1; for (int i = 0; i < input.Count(); i++) result \*= input\[i\].Calculate(Freq); return result; }
This does compile and run, but I have some questions regarding if the multithread calls: 1) Will I h
-
Assume that I have a pipe that consists of sections of variable radiuses and that I want to make calculations at different frequencies. So I want the calculations done at different threads for each frequency, but the list of pipe sections stays the same.
public class PipeSection { public PipeSection(double radius) { this.Radius = radius; } public double Radius { get; set; } public double Calculate(double Frequency) { return Frequency \* this.Radius; } }
To run the frequencies in parallel I use Rx:
CancellationTokenSource ctr = new CancellationTokenSource();
List wn = new List();public MainWindow() { InitializeComponent(); PipeSection\[\] input = { new PipeSection(5), new PipeSection(6), new PipeSection(7) }; wn.AddRange(input); //Calcualte at the frequencies 0,100,2000,3000 var FreqData = new double\[\] { 0, 100, 2000, 3000 }.ToObservable(); FreqData //Off the ui thread .ObserveOn(Scheduler.Default) //Run each thread seperatly .SelectMany(x => Task.Run(() => DoCalcualtions(x,wn), ctr.Token)) //Back to the UI thread .ObserveOnDispatcher() //Subscribe and start the calcualtions .Subscribe(args => { //Update the progressbar when a thread is completed pgbProgress.Value += 1; //Tell me what thread is completed txtText.Text += Environment.NewLine + args.ToString(); }, () => { //All done, here I could do sorting etc. txtText.Text += Environment.NewLine + "All done"; } ); } private double DoCalcualtions(double Freq, List input) { double result=1; for (int i = 0; i < input.Count(); i++) result \*= input\[i\].Calculate(Freq); return result; }
This does compile and run, but I have some questions regarding if the multithread calls: 1) Will I h
As long as your threads don't modify the data they're reading it's all perfectly thread-safe. No need to clone the data or to move
DoCalcualtions
. MovingDoCalcualtions
into thePipeSection
class wouldn't make a lot of sense anyway because it doesn't operate on a singlePipeSection
instance. I assume in practice your input data set is a lot larger so threading is actually called for? There are of course alternative ways of doing this but I don't think there's an objectively better way. You're aware that you're ignoring theCancellationToken
inDoCalcualtions
?If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
-
As long as your threads don't modify the data they're reading it's all perfectly thread-safe. No need to clone the data or to move
DoCalcualtions
. MovingDoCalcualtions
into thePipeSection
class wouldn't make a lot of sense anyway because it doesn't operate on a singlePipeSection
instance. I assume in practice your input data set is a lot larger so threading is actually called for? There are of course alternative ways of doing this but I don't think there's an objectively better way. You're aware that you're ignoring theCancellationToken
inDoCalcualtions
?If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
Thank you for the answer. I understand that they are thread safe, but what I was worried about was that there was just "one function" in memory, so when it was used no other threads could use the function, thereby making the multithreading single thread instead? (So I tried (and failed) to described a wrapper class that had several instances of the function in memory). As for the reasoning behind using multithreading, the datasets itself are not so large, but I'm going to do some numerical integration inside
DoCalcualtions
that is very time-consuming. As for the non-use ofCancellationToken
I just stripped the calculations to the bare minimum. Kenneth
-
Thank you for the answer. I understand that they are thread safe, but what I was worried about was that there was just "one function" in memory, so when it was used no other threads could use the function, thereby making the multithreading single thread instead? (So I tried (and failed) to described a wrapper class that had several instances of the function in memory). As for the reasoning behind using multithreading, the datasets itself are not so large, but I'm going to do some numerical integration inside
DoCalcualtions
that is very time-consuming. As for the non-use ofCancellationToken
I just stripped the calculations to the bare minimum. Kenneth
Kenneth Haugland wrote:
what I was worried about was that there was just "one function" in memory, so when it was used no other threads could use the function, thereby making the multithreading single thread instead?
No, there's no such thing as automatic method-entry-queuing. That's why there are synchronization objects. If you don't use any your threads will execute whatever "comes their way".
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
-
Kenneth Haugland wrote:
what I was worried about was that there was just "one function" in memory, so when it was used no other threads could use the function, thereby making the multithreading single thread instead?
No, there's no such thing as automatic method-entry-queuing. That's why there are synchronization objects. If you don't use any your threads will execute whatever "comes their way".
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
If I read you correctly, each thread will have its own function to use?
-
If I read you correctly, each thread will have its own function to use?
Code (instructions) only exist(s) once in memory and that's not a problem because it (usually) never changes. But each thread has its own stack for local variable allocation. When thread #2 enters
DoCalcualtions
while thread #1 is still executingDoCalcualtions
they will have individual "instances" of the local variableresult
. Ref: memory management - What and where are the stack and heap? - Stack Overflow[^]If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson