Files
sbox-public/engine/Sandbox.Engine/Systems/Threads/MainThread.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

114 lines
2.1 KiB
C#

using System.Threading;
using System.Threading.Channels;
namespace Sandbox;
/// <summary>
/// Utility functions that revolve around the main thread
/// </summary>
public static class MainThread
{
static Channel<IDisposable> Disposables = Channel.CreateUnbounded<IDisposable>();
static Channel<Action> Actions = Channel.CreateUnbounded<Action>();
/// <summary>
/// Wait to execute on the main thread
/// </summary>
public static SyncTask Wait()
{
return new SyncTask( SyncContext.MainThread, allowSynchronous: true );
}
internal static void QueueDispose( IDisposable disposable )
{
if ( disposable is null )
return;
if ( ThreadSafe.IsMainThread )
{
disposable.Dispose();
return;
}
Disposables.Writer.TryWrite( disposable );
}
/// <summary>
/// Run a function on the main thread and wait for the result.
/// </summary>
internal static T Run<T>( int millisecondsTimeout, Func<T> func )
{
if ( ThreadSafe.IsMainThread )
return func();
T r = default;
ManualResetEvent reset = new ManualResetEvent( false );
Queue( () =>
{
try
{
r = func();
}
finally
{
reset.Set();
}
} );
if ( !reset.WaitOne( millisecondsTimeout ) )
{
return default;
}
return r;
}
internal static void RunQueues()
{
ThreadSafe.AssertIsMainThread();
while ( Disposables.Reader.TryRead( out var disposable ) )
{
disposable.Dispose();
}
RunMainThreadQueues();
}
/// <summary>
/// When running in another thread you can queue a method to run in the main thread.
/// If you are on the main thread we will execute the method immediately and return.
/// </summary>
public static void Queue( Action method )
{
if ( ThreadSafe.IsMainThread )
{
method();
return;
}
Actions.Writer.TryWrite( method );
}
/// <summary>
/// Run queued actions on the main thread
/// </summary>
internal static void RunMainThreadQueues()
{
ThreadSafe.AssertIsMainThread();
while ( Actions.Reader.TryRead( out var action ) )
{
try
{
action();
}
catch ( System.Exception e )
{
Log.Warning( e, e.Message );
}
}
}
}