Files
Lorenz Junglas 236b95e0ed Disposable diagnostic (#3693)
* Enable CA2000 in editorconfig

* Remove unused CaptureStdOut class

* Add missing dispose calls in Sandbox.Tools

* Add missing dispose calls in tests

* Add missing dispose calls in launchers

* Add missing dispose calls in Topten.RichtTextKit

* Add missing dispose calls in Engine

* Add missing dispose calls in SboxBuild

* Add nullchecks to a few dispose calls

* Fix more missing disposal calls and leaks

* Disable CA2000 for Textures

* Fix disposing too early in ImageFileTextureGenerator

* Fix disposing codec, ownership is transferred to animation

* Add missing using in ByteStream benchmark
2026-01-12 21:59:15 +01: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;
using var 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 );
}
}
}
}