Author Topic: How to use the WorkerThread script  (Read 3359 times)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
How to use the WorkerThread script
« on: August 01, 2016, 02:54:40 PM »
One of my most useful tools has always been the WorkerThread class, and although not really relevant to anything in TNet itself, I decided to include it in the package in case you too find it useful.

In simplest terms, it's a thread pool that's really easy to use.
  1. WorkerThread.Create(delegate ()
  2. {
  3.     // Do something here that takes up a lot of time
  4. },
  5. delegate ()
  6. {
  7.     Debug.Log("Worker thread finished its long operation!");
  8. });
In the code above, the first delegate is going to be executed on one of the worker threads created by the WorkerThread class. The class will automatically create several, and will reuse them for all of your future jobs. As such, there are no memory allocations happening at run-time. The second delegate is optional, and will execute on the main thread (in the Update() function) when the first delegate has completed its execution.

This dual delegate approach trivializes creation of complex jobs. To pass arguments, you can simply take advantage of how anonymous delegates work. For example this code will take the current terrain and flip it upside-down:
  1. var td = Terrain.activeTerrain.terrainData;
  2. var size = td.heightmapResolution;
  3. var heightmap = td.GetHeights(0, 0, size, size);
  4.  
  5. WorkerThread.Create(delegate ()
  6. {
  7.     for (int y = 0; y < size; ++y)
  8.     {
  9.         for (int x = 0; x < size; ++x)
  10.         {
  11.             heightmap[y, x] = 1f - heightmap[y, x];
  12.         }
  13.     }
  14. },
  15. delegate ()
  16. {
  17.     td.SetHeights(0, 0, heightmap);
  18. });
The worker thread class will work both at run time and edit time, but edit time means it will execute both delegates right away. Currently the project I'm working on uses WorkerThread everywhere -- from ocean height sampling, to merging trees, to generating procedural terrain and textures.

Questions? Ask away.

col000r

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 43
  • Mighty Emperor of Planet "Home Office"
    • View Profile
    • BLACKISH
Re: How to use the WorkerThread script
« Reply #1 on: August 17, 2016, 02:11:51 PM »
Fantastically useful stuff! Thanks for adding it!

It took me a little while to understand what WorkerThread.CreateConditional does. I though it meant that it does something on the thread, then depending on the return value, calls the second delegate - or not. Well, no.

Here is how it really works: The first delegate is called over and over and over until it returns false, then the second delegate is called.

  1. TNet.WorkerThread.CreateConditional(
  2.     delegate() {
  3.         return distance > 100f
  4.     }, delegate() {
  5.         Debug.Log( "Close enough!" );
  6.     }
  7. );
Games: BLACKISH | Blog | Assets

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: How to use the WorkerThread script
« Reply #2 on: August 18, 2016, 12:11:45 AM »
Yeah, I should rename that one... Also it should return 'true' when it's done, not 'false'.

I've also just added a conditional OnFinished version too, so that the finished delegate can execute multiple times. I used it for terrain generation here -- in order to split setting TerrainData.size, calling TerrainData.SetHeightsDelayLOD and Terrain.ApplyDelayedHeightmapModification across 3 frames.