@@ -184,6 +184,17 @@ enum EOSState
184184 static private bool s_isConstrained = true ;
185185 static public bool ApplicationIsConstrained { get => s_isConstrained ; }
186186
187+ /// <summary>
188+ /// Actions that need to be executed on the main thread.
189+ /// Lazy allocated in <see cref="DispatchAsync"/>.
190+ /// </summary>
191+ static private List < Action > s_enqueuedTasks ;
192+
193+ /// <summary>
194+ /// Locak object used for <see cref="s_enqueuedTasks"/>, such that it can
195+ /// be executed thread-safe way.
196+ /// </summary>
197+ static private System . Object s_enqueuedTasksLock = new System . Object ( ) ;
187198 //private static List
188199
189200 //-------------------------------------------------------------------------
@@ -1553,6 +1564,7 @@ public void RemovePersistentToken()
15531564 //-------------------------------------------------------------------------
15541565 public void Tick ( )
15551566 {
1567+ ExecuteQueuedMainThreadTasks ( ) ;
15561568 if ( GetEOSPlatformInterface ( ) != null )
15571569 {
15581570 // Poll for any application constrained state change that didn't
@@ -1941,5 +1953,46 @@ void IEOSCoroutineOwner.StartCoroutine(IEnumerator routine)
19411953 {
19421954 base . StartCoroutine ( routine ) ;
19431955 }
1956+
1957+ /// <summary>
1958+ /// Enqueues an Action to be executed on the main thread.
1959+ /// </summary>
1960+ /// <param name="action">Action to execute.</param>
1961+ static public void DispatchAsync ( Action action )
1962+ {
1963+ lock ( s_enqueuedTasksLock )
1964+ {
1965+ // Lazy allocate the queue
1966+ if ( s_enqueuedTasks == null )
1967+ {
1968+ s_enqueuedTasks = new List < Action > ( ) ;
1969+ }
1970+ s_enqueuedTasks . Add ( action ) ;
1971+ }
1972+ }
1973+
1974+ static private void ExecuteQueuedMainThreadTasks ( )
1975+ {
1976+ // Lock the enqued tasks list, and hold refrence to the enqueued tasks.
1977+ // This is done so that the foreach loop doesn't potentially go "forever"
1978+ // if a given action in the queue happens to generate a list of tasks that
1979+ // also generate a list of task. The s_enqueuedTasks list is also nulled out
1980+ // because we only allocate the list if we need to queue up new tasks. See DispatchSync
1981+ List < Action > actionsToRun ;
1982+ lock ( s_enqueuedTasksLock )
1983+ {
1984+ actionsToRun = s_enqueuedTasks ;
1985+ s_enqueuedTasks = null ;
1986+ if ( actionsToRun == null )
1987+ {
1988+ return ;
1989+ }
1990+ }
1991+
1992+ foreach ( Action action in actionsToRun )
1993+ {
1994+ action . Invoke ( ) ;
1995+ }
1996+ }
19441997 }
19451998}
0 commit comments