JobHandle.CombineDependencies, is there a better way?

Hi there,

In many of my systems I have code that reads like this:

        NativeArray<Item> itemComponentArray = itemQuery.ToComponentDataArrayAsync<Item>( Allocator.TempJob, out JobHandle itemComponentsHandle );
        NativeArray<Entity> itemEntityArray = itemQuery.ToEntityArrayAsync( Allocator.TempJob, out JobHandle itemEntitiesHandle );

        NativeArray<JobHandle> jobs = new NativeArray<JobHandle>( 3, Allocator.Temp );
        jobs[0] = Dependency;
        jobs[1] = itemComponentsHandle;
        jobs[2] = itemEntitiesHandle;

        Dependency = JobHandle.CombineDependencies( jobs );
        jobs.Dispose();

        Entities
            .WithDisposeOnCompletion( itemComponentArray )
            .WithDisposeOnCompletion( itemEntityArray )
            .ForEach( ( ref Inventory inventory ) =>
            {
            } ).Schedule();
    }

I’m creating a bunch of Jobs to go and build the NativeArray of components or entities, then having to wait for those tasks before using them in an Entities.ForEach or Job.WithCode. I do this a lot in many places to take up a little time on the main thread as possible.

I’ve found the code above, using the NativeArray, is the most maintainable version of the code so far as it’s easy to add elements to it.

I was wondering if there’s a more streamlined way of doing this. I feel like the NativeArray could be returned and the JobHandle combined to the SystemBase’s Dependency in one function call.

Is there a neater way of doing this? Have I been writing this out the long way?

Thanks!
Dan

You could write a JobHandle extension method where you can conitnuously combine dependencies together.

public static class JobHandleUtils {
    public static JobHandle CombineWith(this JobHandle lhs, JobHandle rhs) {
        return JobHandle.CombineDependencies(lhs, rhs);
    }
}

// In your system base
Dependency = dep1.CombineWith(dep2).CombineWith(dep3).CombineWith(dep4);

You can probably come up with something a bit more advance if you’d like to stick with using the NativeArray api with extension methods since that will be 1 call to combine N dependencies versus N calls for N dependencies.

Hey Psuong! Thanks very much for your reply.

The extension function that you’ve suggested still needs to have the dependency combined on a second line, which could be forgotten, so I’ve made the following:

using Unity.Entities;
using Unity.Collections;
using Unity.Jobs;

public static class EntityQueryExtensions
{
    public static JobHandle ToComponentDataArrayAsync<T>( this EntityQuery entityQuery, Allocator allocator, out NativeArray<T> nativeArray, JobHandle dependency ) where T : struct , IComponentData
    {
        nativeArray = entityQuery.ToComponentDataArrayAsync<T>( allocator, out JobHandle asyncHandle );
        return JobHandle.CombineDependencies( dependency, asyncHandle );
    }

    public static JobHandle ToEntityArrayAsync( this EntityQuery entityQuery, Allocator allocator, out NativeArray<Entity> nativeArray, JobHandle dependency )
    {
        nativeArray = entityQuery.ToEntityArrayAsync( allocator, out JobHandle asyncHandle );
        return JobHandle.CombineDependencies( dependency, asyncHandle );
    }
}

Now something like this can be done.

Dependency = itemQuery.ToComponentDataArrayAsync<Item>( Allocator.TempJob, out NativeArray<Item> itemComponentArray, Dependency );

This will combine the Dependency and give me a NativeArray back.

Thanks for your help!