@@ -207,6 +207,11 @@ private static bool OnMainThread {
207
207
get { return mainThreadId == System . Threading . Thread . CurrentThread . ManagedThreadId ; }
208
208
}
209
209
210
+ /// <summary>
211
+ /// Set when the current thread is running ExecuteAll().
212
+ /// </summary>
213
+ private static bool runningExecuteAll = false ;
214
+
210
215
/// <summary>
211
216
/// Flag which indicates whether any jobs are running on the main thread.
212
217
/// This is set and cleared by RunAction().
@@ -218,7 +223,7 @@ private static bool OnMainThread {
218
223
/// This property is reset to its' default value after each set of jobs is dispatched.
219
224
/// </summary>
220
225
public static bool ExecuteNow {
221
- get { return ExecutionEnvironment . InBatchMode && ! runningJobs ; }
226
+ get { return ExecutionEnvironment . InBatchMode && ! runningJobs && ! runningExecuteAll ; }
222
227
}
223
228
224
229
/// <summary>
@@ -302,7 +307,7 @@ public static void PollOnUpdateUntilComplete(Func<bool> condition, bool synchron
302
307
if ( ExecuteNow && OnMainThread ) {
303
308
RunAction ( ( ) => {
304
309
while ( true ) {
305
- ExecuteAll ( ) ;
310
+ ExecuteAllUnnested ( true ) ;
306
311
lock ( pollingJobs ) {
307
312
if ( pollingJobs . Count == 0 ) break ;
308
313
}
@@ -316,7 +321,7 @@ public static void PollOnUpdateUntilComplete(Func<bool> condition, bool synchron
316
321
if ( ! pollingJobs . Contains ( condition ) ) break ;
317
322
}
318
323
if ( OnMainThread ) {
319
- ExecuteAll ( ) ;
324
+ ExecuteAllUnnested ( true ) ;
320
325
} else {
321
326
// Wait 100ms.
322
327
Thread . Sleep ( 100 ) ;
@@ -409,7 +414,7 @@ public static void Run(Action job, bool runNow = true) {
409
414
// If we're not executing the job right now, the job queue is pumped from the UnityEditor
410
415
// update event.
411
416
if ( firstJob && ( runNow || ExecuteNow ) && OnMainThread ) {
412
- ExecuteAll ( ) ;
417
+ ExecuteAllUnnested ( false ) ;
413
418
}
414
419
}
415
420
@@ -437,7 +442,7 @@ private static bool ExecuteNext() {
437
442
/// <returns>true if the caller is on the main thread, false otherwise.</returns>
438
443
public static bool TryExecuteAll ( ) {
439
444
if ( OnMainThread ) {
440
- ExecuteAll ( ) ;
445
+ ExecuteAllUnnested ( true ) ;
441
446
return true ;
442
447
}
443
448
return false ;
@@ -446,22 +451,45 @@ public static bool TryExecuteAll() {
446
451
/// <summary>
447
452
/// Execute all scheduled jobs and remove from the update loop if no jobs are remaining.
448
453
/// </summary>
454
+ /// <param name="force">Force execution when a re-entrant call of this method is detected.
455
+ /// This is useful when an application is forcing execution to block the main thread.</param>
449
456
private static void ExecuteAll ( ) {
457
+ ExecuteAllUnnested ( false ) ;
458
+ }
459
+
460
+ /// <summary>
461
+ /// Execute all scheduled jobs and remove from the update loop if no jobs are remaining.
462
+ /// </summary>
463
+ /// <param name="allowNested">Force execution when a re-entrant call of this method is detected.
464
+ /// This is useful when an application is forcing execution to block the main thread.</param>
465
+ private static void ExecuteAllUnnested ( bool allowNested ) {
450
466
if ( ! OnMainThread ) {
451
467
UnityEngine . Debug . LogError ( "ExecuteAll must be executed from the main thread." ) ;
452
468
return ;
453
469
}
454
470
471
+ // Don't nest job execution on the main thread, return to the last stack frame
472
+ // running ExecuteAll().
473
+ if ( runningExecuteAll && ! allowNested ) return ;
474
+
455
475
RunAction ( ( ) => {
456
- // Execute jobs.
457
- while ( ExecuteNext ( ) ) {
458
- }
476
+ runningExecuteAll = true ;
477
+ bool jobsRemaining = true ;
478
+ while ( jobsRemaining ) {
479
+ jobsRemaining = false ;
480
+ // Execute jobs.
481
+ while ( ExecuteNext ( ) ) {
482
+ jobsRemaining = true ;
483
+ }
459
484
460
- // Execute polling jobs.
461
- int remainingJobs ;
462
- do {
463
- remainingJobs = ExecutePollingJobs ( ) ;
464
- } while ( remainingJobs > 0 && ExecutionEnvironment . InBatchMode ) ;
485
+ // Execute polling jobs.
486
+ int remainingJobs = ExecutePollingJobs ( ) ;
487
+ // If we're in batch mode, keep on executing until no polling jobs remain.
488
+ if ( ExecutionEnvironment . InBatchMode && remainingJobs > 0 ) {
489
+ jobsRemaining = true ;
490
+ }
491
+ }
492
+ runningExecuteAll = false ;
465
493
} ) ;
466
494
}
467
495
}
0 commit comments