AstarWorkItem queue / PathQueue: find path, read path, find next

Hello,
For simplicity of explanation: I am making an AI similar to Autochess. There is a playing location (in my case a large size) and, for example, 20 units. I need to find a path for every unit once a second so that they never intersect. Units move only one cell. Thanks to the forum and documentation, I found out that I need to use BlockManager. Since it is very expensive to count all the paths in one frame, I consider 1 path in 1 frame (coroutine). However, there may be situations where the user has less than 20-30 frames. Therefore, I wanted to use AstarWorkItem to calculate all the paths in a separate thread. My logic is:
Block nodes of all units;
For each unit:

  1. Unlock unit node;
  2. Find a path;
  3. If the path size is> 0, then block the node “path [1]”, otherwise block the last node.
    However, in step 3, I still do not have access to the path (is it not calculated?)
    My code is:
        for (int i = 0; i < pathes.Count; i++)
        {
            int k = i;
            AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => { traversalProvider.blockedNodes.Remove(AstarPath.active.GetNearest(ts[k].position).node); }));
            AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => { AstarPath.StartPath(pathes[k]); }));
            AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => { Debug.LogError(pathes[k].vectorPath.Count); }));
          //  AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => { traversalProvider.selector.Add(pathes[k].path[0]);      
         //   }));
        }

In general, I want instead of each frame to cause logic for the next unit, just put all the units in the queue. Is it possible? Or the only way is to process 1 path in 1 frame?

Thanks.

P.S. I wrote my CustonTraversalProvider, which simply accepts an array of locked nodes.

Hi

I would do something like

for (int i = 0; i < paths.Count; i++) {
     traversalProvider.blockedNodes.Remove(AstarPath.active.GetNearest(ts[i].position).node);
     AstarPath.StartPath(paths[i]);
     for (int w = 0; w < delayFrames; w++) yield return null;
     paths[0].BlockUntilCalculated();
     traversalProvider.selector.Add(paths[i].path[1]);
}

Then you can have delayFrames set to 1 most of the time, but if you are running out of time you can set it to 0 to make all paths be calculated instantly.

Note that work items are always executed in the main thread.

That is, there is no way to perform a chain of calculation of paths and changes to traversalProvider in a separate thread?
Ok, I get it, thanks.

Well, you can use path.immediateCallback which will be called from the pathfinding thread itself.
So something like

void SearchPath(int pathIndex) {
    traversalProvider.blockedNodes.Remove(AstarPath.active.GetNearest(ts[pathIndex].position).node);
    paths[pathIndex].immediateCallback = (p) => {
        traversalProvider.selector.Add(paths[pathIndex].path[1]);
        if (pathIndex + 1 < paths.Count) SearchPath(pathIndex + 1);
    };
    AstarPath.StartPath(paths[pathIndex]);
}

void SearchAllPaths() {
    SearchPath(0);

    // If you need to calculate all paths immediately
    // paths[paths.Count-1].BlockUntilCalculated();
}

Be very careful when doing this though. Multithreaded race conditions are hell to deal with.
See https://arongranberg.com/astar/docs/path.html#immediateCallback

I get an error:

UnityException: get_isPlaying can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
AstarPath.StartPath (Pathfinding.Path path, System.Boolean pushToFront) (at Assets/AstarPathfindingProject/Core/AstarPath.cs:1969)
ManyAgentsTest.SearchPathInGlobalQueue (System.Int32 pathIndex) (at Assets/ManyAgentsTest.cs:59)
ManyAgentsTest+<>c__DisplayClass9_0.<SearchPathInGlobalQueue>b__0 (Pathfinding.Path p) (at Assets/ManyAgentsTest.cs:57)
Pathfinding.PathProcessor.CalculatePathsThreaded (Pathfinding.PathHandler pathHandler) (at Assets/AstarPathfindingProject/Core/Misc/PathProcessor.cs:376)
UnityEngine.Debug:LogException(Exception)
Pathfinding.PathProcessor:CalculatePathsThreaded(PathHandler) (at Assets/AstarPathfindingProject/Core/Misc/PathProcessor.cs:407)
Pathfinding.<>c__DisplayClass24_0:<.ctor>b__0() (at Assets/AstarPathfindingProject/Core/Misc/PathProcessor.cs:110)
System.Threading.ThreadHelper:ThreadStart()

		// Outside of play mode, all path requests are synchronous
		if (!Application.isPlaying) {
			BlockUntilCalculated(path);
		}

(v 4.3.14 (pro), Unity 2019.3.0f6)

I commented out this lines, but how much is it provided and safe?