There’s quite different ways to use threading, roughly:
-Slice based threading (several threads runs part of the operation). That works really well for simple operations with high spread count (or more complex ones like attractor). On low spread count it can be very expensive instead. Finding the “sweet spot” (eg: when threading overcomes non threaded) is quite a pain, depends a lot on your operation/processor. Also i found slice based threading quite very varying time wise (between 2 executions), I prefer sse/avx results are much predictable (you can do both of course, but for a threaded version of something like + (Value) i need a spread count of 100000 for threading to beat sse…
in c# you create several threads to process part of the spread then use Join at the end.
For simple operations (anything without states), if you not scared of using c++ take a look at openmp, just makes c# threading look crap in ease of use/performance.
-Task based threading: you can have something like fluidsolver copying all density data in a thread, velocity in another one, then join. It’s a bit same concept as above, but for 2 operations instead. (openmp equally outshines c# at task parallel operations).
-Background based threading:
for example you could upload a file to ftp server in a thread, then send back progress/success/failure operation as feedback. Very easy to do although have to be careful when input changes on what action you want to take.
Also you could make a complex operation and output result when ready, just have to learn how to do a bit of sync (using locks), single locks are simple, multiple locks can be let’s call it “fun” ;)
not implemented in directx 9, not a chance ;)
Feel free to ask more questions :)