// For convenience, this call has all of the parameters as the main call, except the jobIdToUnPauseWhenDone parameter, which is set automatically // This method is really "Start a new job, and if it does not complete immediately, pause the calling job, and register that it will be un-paused when the new job completes" public uint StartJobAndPause ( IEnumerator job, OnJobCompletionHandler completionHandler = null, OnJobCancellationHandler cancellationHandler = null, string jobName = "", List <uint> dependentJobs = null, float timeoutTime = Single.MaxValue, int maxExecutionsPerFrame = Int32.MaxValue, bool canSkipFrames = false, bool startImmediately = false ) { if (CurrentlyRunningJobId == UInt32.MaxValue) { throw new Exception("JobManager: Call to StartJobAndPause received from code that is not a job"); } var id = StartJob(job, completionHandler, cancellationHandler, jobName, dependentJobs, timeoutTime, maxExecutionsPerFrame, canSkipFrames, startImmediately, CurrentlyRunningJobId); if (RegisteredJobs.ContainsKey(id)) // If the job has not already finished { PauseJob(CurrentlyRunningJobId); } return(id); }
public uint StartJob ( IEnumerator job, OnJobCompletionHandler completionHandler = null, OnJobCancellationHandler cancellationHandler = null, string jobName = "", List <uint> dependentJobs = null, float timeoutTime = Single.MaxValue, int maxExecutionsPerFrame = Int32.MaxValue, bool canSkipFrames = false, bool startImmediately = false, // Note that if startImmediately is set to true, the time budgeting for the current frame might be thrown off uint jobIdToUnPauseWhenDone = UInt32.MaxValue ) { uint id = NextUid++; if (jobName.Equals("")) { jobName = "(unnamed)"; } RegisteredJobs[id] = new Job(); // Add to the list of registered jobs PRIOR to launching the coroutine, since the job might finish immediately var jobEntry = RegisteredJobs[id]; jobEntry.Coroutine = null; jobEntry.JobCompletionHandler = completionHandler; jobEntry.JobCancellationHandler = cancellationHandler; jobEntry.Name = jobName; if (dependentJobs == null) { jobEntry.DependentJobs = new List <uint>( ); // This is because we can't pass a non-null default item as a function parameter above if the item is a reference } else { // This rule (dependent jobs must have been registered prior to the dependee) prevents circularity if (dependentJobs.Any(jobId => jobId >= id)) { throw new Exception("JobManager: Error starting job \"" + jobName + "\"; invalid dependent job ID (must be a job that has already been started)"); } jobEntry.DependentJobs = dependentJobs; // For all the dependent jobs, ensure they can't skip frames (that could cause a lockup) foreach (var jobId in dependentJobs) { if (RegisteredJobs.ContainsKey(jobId)) { RegisteredJobs[jobId].CanSkipFrames = false; } } } jobEntry.TimeoutTimeInTicks = (timeoutTime > 1e20f ? Int64.MaxValue : Stopwatch.Frequency * (long)timeoutTime); jobEntry.MaxExecutionsPerFrame = maxExecutionsPerFrame; jobEntry.CanSkipFrames = canSkipFrames; jobEntry.JobIdToUnPauseWhenDone = jobIdToUnPauseWhenDone; jobEntry.State = JobState.Running; jobEntry.FinishJobNow = false; var coroutine = StartCoroutine(RunJob(id, job, startImmediately)); // Now that we have a reference to the coroutine, we can save it in the dictionary. However the job may have ran // and immediately finished by the time we get here, so in that case the registered item has already been removed. if (RegisteredJobs.ContainsKey(id)) { RegisteredJobs[id].Coroutine = coroutine; } return(id); }