Last active
November 4, 2025 10:02
-
-
Save rtm223/f1eb1360beba7bef11fae4ca8624f32e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Copyright (C) Richard Meredith 2017 | |
| // Licensed under the MIT License https://opensource.org/licenses/MIT | |
| // this is source code related to the blog post I wrote on Multithreading back in 2017 | |
| // https://richardmeredith.net/2017/11/pause-resume-abort-multithreading-unity/ | |
| // Moving this code into a Gist for archival purposes | |
| // The blog post was written a long time ago (using Unity 5.5 apparently!) and as such | |
| // the implementation details are outdated and I'm not familiar enough with Unity these | |
| // days to know what the correct approach would be. I'm pretty sure Unity has similar | |
| // helper classes built-in now, but the concepts and information here are still useful | |
| using System; | |
| using System.Collections; | |
| using System.Threading; | |
| public class ThreadWorker | |
| { | |
| private Thread ChildThread = null; | |
| private EventWaitHandle SuspendHandle = new EventWaitHandle(true, EventResetMode.ManualReset); | |
| private EventWaitHandle AbortHandle = new EventWaitHandle(false, EventResetMode.ManualReset); | |
| private bool WantAbort = false; | |
| public ThreadWorker(IEnumerator threadImplementation) : this() | |
| { | |
| Start(threadImplementation); | |
| } | |
| public void Start(IEnumerator threadImplementation) | |
| { | |
| ChildThread = new Thread(ThreadLoop); | |
| ChildThread.Start(threadImplementation); | |
| } | |
| public void Resume() | |
| { | |
| SuspendHandle.Set(); | |
| } | |
| public void Suspend() | |
| { | |
| if(!WantAbort) | |
| SuspendHandle.Reset(); | |
| } | |
| public void Abort(bool block=true) | |
| { | |
| WantAbort = true; | |
| Resume(); | |
| if(block) | |
| AbortHandle.WaitOne(); | |
| } | |
| private void ThreadLoop(object threadImplementation) | |
| { | |
| try | |
| { | |
| var impl = threadImplementation as IEnumerator; | |
| while(!WantAbort && impl.MoveNext()) | |
| { | |
| if(WantAbort) | |
| break; | |
| SuspendHandle.WaitOne(); | |
| } | |
| } | |
| catch(Exception e) | |
| { | |
| WantAbort = true; | |
| UnityEngine.Debug.LogException(e); | |
| } | |
| AbortHandle.Set(); | |
| ChildThread = null; | |
| } | |
| public bool IsRunning() {return ChildThread != null;} | |
| public bool IsCompleted() {return ChildThread == null;} | |
| #if UNITY_EDITOR | |
| public ThreadWorker() | |
| { | |
| UnityEditor.EditorApplication.playmodeStateChanged += HandleEditorPlayModeChanged; | |
| } | |
| ~ThreadWorker() | |
| { | |
| UnityEditor.EditorApplication.playmodeStateChanged -= HandleEditorPlayModeChanged; | |
| } | |
| void HandleEditorPlayModeChanged() | |
| { | |
| if(IsRunning()) | |
| { | |
| if(UnityEditor.EditorApplication.isPaused) | |
| Suspend(); | |
| else | |
| Resume(); | |
| } | |
| } | |
| #else | |
| public ThreadWorker() {} | |
| #endif | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment