I implemented my own “job” type to which I can pass managed types. This is my inspiration and here’s my implementation:
Code
public interface IJobManaged
{
void Execute();
}
public static class IJobManagedExtensions
{
public static JobHandle Schedule<T>(this T jobDependentCodeData,
JobHandle dependsOn = default)
where T : struct,IJobManaged
{
GCHandle gcHandle = GCHandle.Alloc(jobDependentCodeData);
var jobHandle = new GCHandleJob()
{
handle = gcHandle
}.Schedule(dependsOn);
IJobManagedCoroutineStarter.StartTask(GetGCHandleFreeCoroutine(gcHandle,jobHandle));
return jobHandle;
}
private static IEnumerator GetGCHandleFreeCoroutine(GCHandle gcHandle, JobHandle jobHandle)
{
while (!jobHandle.IsCompleted)
{
//Debug.Log("AAAAAA"); if I uncomment this, everything works fine
yield return null;
}
Debug.Log("Free");
gcHandle.Free();
}
private struct GCHandleJob : IJob
{
public GCHandle handle;
public void Execute()
{
IJobManaged task = (IJobManaged) handle.Target;
task.Execute();
}
}
}
And I have a problem running following code:
public void ManagedJobTest()
{
Debug.Log("Test");
NativeArray<float> a = new NativeArray<float>(100000,Allocator.Persistent);
a[0] = 7.557f;
var jobHandle = new JobManagedTest()
{
a = a
}.Schedule(new JobHandle());
var jobHandle2 = new JobManagedTest()
{
a = a
}.Schedule(jobHandle);
a.Dispose(jobHandle2);
}
private struct JobManagedTest : IJobManaged
{
public NativeArray<float> a;
public void Execute()
{
Debug.Log(a[0]);
}
}
The thing is everything works fine when Debug.Log in GetGCHandleFreeCoroutine is uncommented but if it isn’t there I get:
InvalidOperationException: The Unity.Collections.NativeArray`1[System.Single] has been declared as [WriteOnly] in the job, but you are reading from it.
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <9dd7ba599535486bb48a2633dd80a88b>:0)
Unity.Collections.NativeArray`1[T].CheckElementReadAccess (System.Int32 index) (at <9dd7ba599535486bb48a2633dd80a88b>:0)
Unity.Collections.NativeArray`1[T].get_Item (System.Int32 index) (at <9dd7ba599535486bb48a2633dd80a88b>:0)
Why does it happen and why simple Debug.Log makes it work? It also works when I get rid of a.Dispose() but that’s not viable solution because it would be a memory leak