Search Unity

How to dispose NativeArray with ForEach lambda?

Discussion in 'Entity Component System' started by colin_young, Jan 14, 2020.

  1. colin_young

    colin_young

    Joined:
    Jun 1, 2017
    Posts:
    243
    I recently converted one of my jobs to use the ForEach style instead of the IJobForEachWithEntity struct style. After converting I started to see "A Native Collection has not been disposed" exceptions. Mostly, I suspect because previously I was able to mark the collections for disposal after the job completes with the DeallocateOnJobCompletion attribute. This is what my code looks like:

    Code (CSharp):
    1.             var laneExitBuffer = GetBufferFromEntity<LaneExitEntity>(true);
    2.  
    3.             NativeArray<Unity.Mathematics.Random> RandomGenerator = new NativeArray<Unity.Mathematics.Random>(JobsUtility.MaxJobThreadCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
    4.  
    5.             for (int i = 0; i < JobsUtility.MaxJobThreadCount; i++)
    6.             {
    7.                 RandomGenerator[i] = new Unity.Mathematics.Random((uint)randomSource.NextInt());
    8.             }
    9.  
    10.             var CommandBuffer = _entityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
    11.  
    12.             var job = Entities.WithAll<NeedsNextLaneTag, ERAutoTag>()
    13.                 .ForEach((Entity entity,
    14.                           int entityInQueryIndex,
    15.                           int nativeThreadIndex,
    16.                           ref VehicleLaneComponent vehicleLaneComponent) =>
    17.                 {
    18.                     // ... snip ...
    19.                 })
    20.                 .WithReadOnly(laneExitBuffer)
    21.                 .Schedule(inputDeps);
    22.  
    23.             _entityCommandBufferSystem.AddJobHandleForProducer(job);
    24.  
    25.             return job;
    26.  
    The offending collection is RandomGenerator. How do I properly dispose of that collection?
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Put .WithDeallocateOnJobCompletion(RandomGenerator) to the ForEach then you can think there is an another job with dependency to that job that perform the Dispose.
     
    florianhanke likes this.
  3. colin_young

    colin_young

    Joined:
    Jun 1, 2017
    Posts:
    243
    Thanks! I was looking for something similar to that. Don't know how I missed it.
     
  4. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    You can also do this:
    Code (CSharp):
    1.  
    2. job = RandomGenerator.Dispose(job);
    3.  
    Also for the random generator you could use this:
    Code (CSharp):
    1.  
    2. inputDeps = Job
    3.     .WithCode(() => {
    4.         for (int i = 0; i < randomGenerator.Length; i++)
    5.         {
    6.             RandomGenerator[i] = new Unity.Mathematics.Random((uint)RandomSource.NextInt());
    7.         }
    8.     })
    9.     .Schedule(inputDeps);
    10.  
    []'s
     
    florianhanke likes this.