Skip to content

Instantly share code, notes, and snippets.

@rtm223
Last active November 4, 2025 10:02
Show Gist options
  • Select an option

  • Save rtm223/f1eb1360beba7bef11fae4ca8624f32e to your computer and use it in GitHub Desktop.

Select an option

Save rtm223/f1eb1360beba7bef11fae4ca8624f32e to your computer and use it in GitHub Desktop.
// 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