JobHandle和依赖
当您调用Job的Schedule方法时,它将返回JobHandle。您可以在代码中使用JobHandle 作为其他Job的依赖。如果一个Job依赖于另一个Job的结果,则可以将第一个Job的JobHandle参数作为参数传递给第二个Job的Schedule方法,如下所示:
JobHandle firstJobHandle = firstJob.Schedule();
secondJob.Schedule(firstJobHandle);
合并依赖(Combining dependencies)
如果Job具有许多依赖关系,则可以使用JobHandle.CombineDependencies方法合并它们。CombineDependencies允许您将它们(JobHandle)作为参数。
NativeArray<JobHandle> handles = new NativeArray<JobHandle>(numJobs, Allocator.TempJob);
// Populate `handles` with `JobHandles` from multiple scheduled jobs...
JobHandle jh = JobHandle.CombineDependencies(handles);
在主线程中等待Job
使用JobHandle就会强制让你在主线程中等待Job完成执行。为此,请在调用JobHandle的Complete方法。至此,您知道主线程可以安全地访问作业正在使用的NativeContainer。
注意:在安排(schedule)Job时,它们(Job)并不会开始执行。如果您正在主线程中等待Job,并且需要访问该Job正在使用的NativeContainer数据,则可以调用方法JobHandle.Complete。此方法从内存缓存中清除作业,并开始执行。JobHandle调用Complete将返回NativeContainer类型的数据的所有权到主线程【可以理解主线程接管了NativeContainer】。也就是说您需要调用Complete才能在再次主线程中安全的访问NativeContainer【原文有确实有again这个词,我理解的再次的意思是:因为一开始NativeContainer是在主线程中创建的,这时Job还没有执行,当调用Complete后,主线程才能从NativeContainer获得结果,所以叫再次访问 】。
通过调用Job依赖的JobHandle的Complete ,也可以将所有权返回给主线程。例如,有两个Job ,其中JobA 依赖JobB。你可以调用JobA的Complete,或者JobB的Complete。两者都可以让你在主线程安全地访问NativeContainer【JobA的结果】。
如果不需要访问数据,则需要显式刷新批处理( batch)。为此,请调用静态方法JobHandle.ScheduleBatchedJobs。请注意,调用此方法可能会对性能产生负面影响。
举个关于多个Job依赖的栗子
Job代码
// Job adding two floating point values together
public struct MyJob : IJob
{
public float a;
public float b;
public NativeArray<float> result;
public void Execute()
{
result[0] = a + b;
}
}
// Job adding one to a value
public struct AddOneJob : IJob
{
public NativeArray<float> result;
public void Execute()
{
result[0] = result[0] + 1;
}
}
主线程代码
// Create a native array of a single float to store the result in. This example waits for the job to complete
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
// Setup the data for job #1
MyJob jobData = new MyJob();
jobData.a = 10;
jobData.b = 10;
jobData.result = result;
// Schedule job #1
JobHandle firstHandle = jobData.Schedule();
// Setup the data for job #2
AddOneJob incJobData = new AddOneJob();
incJobData.result = result;
// Schedule job #2
JobHandle secondHandle = incJobData.Schedule(firstHandle);
// Wait for job #2 to complete
secondHandle.Complete();
// All copies of the NativeArray point to the same memory, you can access the result in "your" copy of the NativeArray
float aPlusB = result[0];
// Free the memory allocated by the result array
result.Dispose();