using Speckle.InterfaceGenerator; namespace Speckle.Connectors.Common.Threading; [GenerateAutoInterface] public abstract class ThreadContext : IThreadContext { private static readonly Task s_empty = Task.FromResult(null); public virtual bool IsMainThread => Environment.CurrentManagedThreadId == 1; public async Task RunOnThread(Action action, bool useMain) { if (useMain) { if (IsMainThread) { await RunMain(action); } else { await WorkerToMain(() => { action(); return s_empty; }); } } else { if (IsMainThread) { await MainToWorker(() => { action(); return s_empty; }); } else { await RunWorker(action); } } } public Task RunOnThread(Func action, bool useMain) { if (useMain) { if (IsMainThread) { return RunMainAsync(action); } return WorkerToMain(action); } if (IsMainThread) { return MainToWorker(action); } return RunWorkerAsync(action); } public async Task RunOnThreadAsync(Func action, bool useMain) { if (useMain) { if (IsMainThread) { await RunMainAsync(action); } else { await WorkerToMainAsync(async () => { await action(); return s_empty; }); } } else { if (IsMainThread) { await MainToWorkerAsync(async () => { await action(); return s_empty; }); } else { if (useMain) { await RunMainAsync(action); } else { await RunWorkerAsync(action); } } } } public Task RunOnThreadAsync(Func> action, bool useMain) { if (useMain) { if (IsMainThread) { return RunMainAsync(action); } return WorkerToMainAsync(action); } if (IsMainThread) { return MainToWorkerAsync(action); } return RunWorkerAsync(action); } protected abstract Task WorkerToMainAsync(Func> action); protected abstract Task MainToWorkerAsync(Func> action); protected abstract Task WorkerToMain(Func action); protected abstract Task MainToWorker(Func action); protected virtual Task RunMain(Action action) { action(); return Task.CompletedTask; } protected virtual Task RunWorker(Action action) { action(); return Task.CompletedTask; } protected virtual Task RunMainAsync(Func action) => Task.FromResult(action()); protected virtual Task RunWorkerAsync(Func action) => Task.FromResult(action()); protected virtual Task RunMainAsync(Func action) => Task.FromResult(action()); protected virtual Task RunWorkerAsync(Func action) => Task.FromResult(action()); protected virtual Task RunMainAsync(Func> action) => action(); protected virtual Task RunWorkerAsync(Func> action) => action(); }