mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Merge pull request #1724 from goatcorp/net8-rollup
[net8] Rollup changes from master
This commit is contained in:
commit
7fcd10ecd8
4 changed files with 314 additions and 26 deletions
|
|
@ -108,9 +108,6 @@ internal sealed class Framework : IInternalDisposableService, IFramework
|
|||
/// <inheritdoc/>
|
||||
public DateTime LastUpdateUTC { get; private set; } = DateTime.MinValue;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TaskFactory FrameworkThreadTaskFactory { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TimeSpan UpdateDelta { get; private set; } = TimeSpan.Zero;
|
||||
|
||||
|
|
@ -130,6 +127,11 @@ internal sealed class Framework : IInternalDisposableService, IFramework
|
|||
/// </summary>
|
||||
internal bool DispatchUpdateEvents { get; set; } = true;
|
||||
|
||||
private TaskFactory FrameworkThreadTaskFactory { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TaskFactory GetTaskFactory() => this.FrameworkThreadTaskFactory;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task DelayTicks(long numTicks, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
|
@ -143,6 +145,38 @@ internal sealed class Framework : IInternalDisposableService, IFramework
|
|||
return tcs.Task;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task RunOnFrameworkThreadAwaitable(Action action, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
cancellationToken = this.FrameworkThreadTaskFactory.CancellationToken;
|
||||
return this.FrameworkThreadTaskFactory.StartNew(action, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<T> RunOnFrameworkThreadAwaitable<T>(Func<T> action, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
cancellationToken = this.FrameworkThreadTaskFactory.CancellationToken;
|
||||
return this.FrameworkThreadTaskFactory.StartNew(action, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task RunOnFrameworkThreadAwaitable(Func<Task> action, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
cancellationToken = this.FrameworkThreadTaskFactory.CancellationToken;
|
||||
return this.FrameworkThreadTaskFactory.StartNew(action, cancellationToken).Unwrap();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<T> RunOnFrameworkThreadAwaitable<T>(Func<Task<T>> action, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
cancellationToken = this.FrameworkThreadTaskFactory.CancellationToken;
|
||||
return this.FrameworkThreadTaskFactory.StartNew(action, cancellationToken).Unwrap();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<T> RunOnFrameworkThread<T>(Func<T> func) =>
|
||||
this.IsInFrameworkUpdateThread || this.IsFrameworkUnloading ? Task.FromResult(func()) : this.RunOnTick(func);
|
||||
|
|
@ -198,7 +232,9 @@ internal sealed class Framework : IInternalDisposableService, IFramework
|
|||
this.DelayTicks(delayTicks, cancellationToken),
|
||||
},
|
||||
_ => func(),
|
||||
cancellationToken);
|
||||
cancellationToken,
|
||||
TaskContinuationOptions.HideScheduler,
|
||||
this.frameworkThreadTaskScheduler);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
@ -223,7 +259,9 @@ internal sealed class Framework : IInternalDisposableService, IFramework
|
|||
this.DelayTicks(delayTicks, cancellationToken),
|
||||
},
|
||||
_ => action(),
|
||||
cancellationToken);
|
||||
cancellationToken,
|
||||
TaskContinuationOptions.HideScheduler,
|
||||
this.frameworkThreadTaskScheduler);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
@ -248,7 +286,9 @@ internal sealed class Framework : IInternalDisposableService, IFramework
|
|||
this.DelayTicks(delayTicks, cancellationToken),
|
||||
},
|
||||
_ => func(),
|
||||
cancellationToken).Unwrap();
|
||||
cancellationToken,
|
||||
TaskContinuationOptions.HideScheduler,
|
||||
this.frameworkThreadTaskScheduler).Unwrap();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
@ -273,7 +313,9 @@ internal sealed class Framework : IInternalDisposableService, IFramework
|
|||
this.DelayTicks(delayTicks, cancellationToken),
|
||||
},
|
||||
_ => func(),
|
||||
cancellationToken).Unwrap();
|
||||
cancellationToken,
|
||||
TaskContinuationOptions.HideScheduler,
|
||||
this.frameworkThreadTaskScheduler).Unwrap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -498,9 +540,6 @@ internal class FrameworkPluginScoped : IInternalDisposableService, IFramework
|
|||
/// <inheritdoc/>
|
||||
public DateTime LastUpdateUTC => this.frameworkService.LastUpdateUTC;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TaskFactory FrameworkThreadTaskFactory => this.frameworkService.FrameworkThreadTaskFactory;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TimeSpan UpdateDelta => this.frameworkService.UpdateDelta;
|
||||
|
||||
|
|
@ -518,10 +557,29 @@ internal class FrameworkPluginScoped : IInternalDisposableService, IFramework
|
|||
this.Update = null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TaskFactory GetTaskFactory() => this.frameworkService.GetTaskFactory();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task DelayTicks(long numTicks, CancellationToken cancellationToken = default) =>
|
||||
this.frameworkService.DelayTicks(numTicks, cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task RunOnFrameworkThreadAwaitable(Action action, CancellationToken cancellationToken = default) =>
|
||||
this.frameworkService.RunOnFrameworkThreadAwaitable(action, cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<T> RunOnFrameworkThreadAwaitable<T>(Func<T> action, CancellationToken cancellationToken = default) =>
|
||||
this.frameworkService.RunOnFrameworkThreadAwaitable(action, cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task RunOnFrameworkThreadAwaitable(Func<Task> action, CancellationToken cancellationToken = default) =>
|
||||
this.frameworkService.RunOnFrameworkThreadAwaitable(action, cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<T> RunOnFrameworkThreadAwaitable<T>(Func<Task<T>> action, CancellationToken cancellationToken = default) =>
|
||||
this.frameworkService.RunOnFrameworkThreadAwaitable(action, cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<T> RunOnFrameworkThread<T>(Func<T> func)
|
||||
=> this.frameworkService.RunOnFrameworkThread(func);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Dalamud.Interface.ImGuiNotification.Internal;
|
|||
/// <summary>Class handling notifications/toasts in ImGui.</summary>
|
||||
[InterfaceVersion("1.0")]
|
||||
[ServiceManager.EarlyLoadedService]
|
||||
internal class NotificationManager : INotificationManager, IServiceType, IDisposable
|
||||
internal class NotificationManager : INotificationManager, IInternalDisposableService
|
||||
{
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly GameGui gameGui = Service<GameGui>.Get();
|
||||
|
|
@ -51,7 +51,7 @@ internal class NotificationManager : INotificationManager, IServiceType, IDispos
|
|||
private IFontAtlas PrivateAtlas { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
public void DisposeService()
|
||||
{
|
||||
this.PrivateAtlas.Dispose();
|
||||
foreach (var n in this.pendingNotifications)
|
||||
|
|
@ -129,7 +129,7 @@ internal class NotificationManager : INotificationManager, IServiceType, IDispos
|
|||
#pragma warning disable SA1015
|
||||
[ResolveVia<INotificationManager>]
|
||||
#pragma warning restore SA1015
|
||||
internal class NotificationManagerPluginScoped : INotificationManager, IServiceType, IDisposable
|
||||
internal class NotificationManagerPluginScoped : INotificationManager, IInternalDisposableService
|
||||
{
|
||||
private readonly LocalPlugin localPlugin;
|
||||
private readonly ConcurrentDictionary<IActiveNotification, int> notifications = new();
|
||||
|
|
@ -151,7 +151,7 @@ internal class NotificationManagerPluginScoped : INotificationManager, IServiceT
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
public void DisposeService()
|
||||
{
|
||||
while (!this.notifications.IsEmpty)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -144,9 +144,7 @@ internal class TaskSchedulerWidget : IDataWindowWidget
|
|||
_ = framework.RunOnTick(() => Log.Information("Framework.Update - In 2s+60f"), cancellationToken: this.taskSchedulerCancelSource.Token, delay: TimeSpan.FromSeconds(2), delayTicks: 60);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("Every 60 frames"))
|
||||
if (ImGui.Button("Every 60f"))
|
||||
{
|
||||
_ = framework.RunOnTick(
|
||||
async () =>
|
||||
|
|
@ -154,6 +152,8 @@ internal class TaskSchedulerWidget : IDataWindowWidget
|
|||
for (var i = 0L; ; i++)
|
||||
{
|
||||
Log.Information($"Loop #{i}; MainThread={ThreadSafety.IsMainThread}");
|
||||
var it = i;
|
||||
_ = Task.Factory.StartNew(() => Log.Information($" => Sub #{it}; MainThread={ThreadSafety.IsMainThread}"));
|
||||
await framework.DelayTicks(60, this.taskSchedulerCancelSource.Token);
|
||||
}
|
||||
},
|
||||
|
|
@ -162,6 +162,68 @@ internal class TaskSchedulerWidget : IDataWindowWidget
|
|||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("Every 1s"))
|
||||
{
|
||||
_ = framework.RunOnTick(
|
||||
async () =>
|
||||
{
|
||||
for (var i = 0L; ; i++)
|
||||
{
|
||||
Log.Information($"Loop #{i}; MainThread={ThreadSafety.IsMainThread}");
|
||||
var it = i;
|
||||
_ = Task.Factory.StartNew(() => Log.Information($" => Sub #{it}; MainThread={ThreadSafety.IsMainThread}"));
|
||||
await Task.Delay(TimeSpan.FromSeconds(1), this.taskSchedulerCancelSource.Token);
|
||||
}
|
||||
},
|
||||
cancellationToken: this.taskSchedulerCancelSource.Token);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("Every 60f (Await)"))
|
||||
{
|
||||
_ = framework.RunOnFrameworkThreadAwaitable(
|
||||
async () =>
|
||||
{
|
||||
for (var i = 0L; ; i++)
|
||||
{
|
||||
Log.Information($"Loop #{i}; MainThread={ThreadSafety.IsMainThread}");
|
||||
var it = i;
|
||||
_ = Task.Factory.StartNew(() => Log.Information($" => Sub #{it}; MainThread={ThreadSafety.IsMainThread}"));
|
||||
await framework.DelayTicks(60, this.taskSchedulerCancelSource.Token);
|
||||
}
|
||||
},
|
||||
this.taskSchedulerCancelSource.Token);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("Every 1s (Await)"))
|
||||
{
|
||||
_ = framework.RunOnFrameworkThreadAwaitable(
|
||||
async () =>
|
||||
{
|
||||
for (var i = 0L; ; i++)
|
||||
{
|
||||
Log.Information($"Loop #{i}; MainThread={ThreadSafety.IsMainThread}");
|
||||
var it = i;
|
||||
_ = Task.Factory.StartNew(() => Log.Information($" => Sub #{it}; MainThread={ThreadSafety.IsMainThread}"));
|
||||
await Task.Delay(TimeSpan.FromSeconds(1), this.taskSchedulerCancelSource.Token);
|
||||
}
|
||||
},
|
||||
this.taskSchedulerCancelSource.Token);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("As long as it's in Framework Thread"))
|
||||
{
|
||||
Task.Run(async () => await framework.RunOnFrameworkThread(() => { Log.Information("Task dispatched from non-framework.update thread"); }));
|
||||
framework.RunOnFrameworkThread(() => { Log.Information("Task dispatched from framework.update thread"); }).Wait();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("Error in 1s"))
|
||||
{
|
||||
_ = framework.RunOnTick(() => throw new Exception("Test Exception"), cancellationToken: this.taskSchedulerCancelSource.Token, delay: TimeSpan.FromSeconds(1));
|
||||
|
|
@ -169,10 +231,18 @@ internal class TaskSchedulerWidget : IDataWindowWidget
|
|||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("As long as it's in Framework Thread"))
|
||||
if (ImGui.Button("Freeze 1s"))
|
||||
{
|
||||
Task.Run(async () => await framework.RunOnFrameworkThread(() => { Log.Information("Task dispatched from non-framework.update thread"); }));
|
||||
framework.RunOnFrameworkThread(() => { Log.Information("Task dispatched from framework.update thread"); }).Wait();
|
||||
_ = framework.RunOnFrameworkThread(() => Helper().Wait());
|
||||
static async Task Helper() => await Task.Delay(1000);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("Freeze Completely"))
|
||||
{
|
||||
_ = framework.RunOnFrameworkThreadAwaitable(() => Helper().Wait());
|
||||
static async Task Helper() => await Task.Delay(1000);
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader("Download"))
|
||||
|
|
@ -217,7 +287,7 @@ internal class TaskSchedulerWidget : IDataWindowWidget
|
|||
this.downloadState = default;
|
||||
var factory = downloadUsingGlobalScheduler
|
||||
? Task.Factory
|
||||
: framework.FrameworkThreadTaskFactory;
|
||||
: framework.GetTaskFactory();
|
||||
this.downloadState = default;
|
||||
this.downloadTask = factory.StartNew(
|
||||
async () =>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,29 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Interface.Internal.Windows.Data.Widgets;
|
||||
|
||||
namespace Dalamud.Plugin.Services;
|
||||
|
||||
/// <summary>
|
||||
/// This class represents the Framework of the native game client and grants access to various subsystems.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><b>Choosing between <c>RunOnFrameworkThread</c> and <c>RunOnFrameworkThreadAwaitable</c></b></para>
|
||||
/// <ul>
|
||||
/// <li>If you do need to do use <c>await</c> and have your task keep executing on the main thread after waiting is
|
||||
/// done, use <c>RunOnFrameworkThreadAwaitable</c>.</li>
|
||||
/// <li>If you need to call <see cref="Task.Wait()"/> or <see cref="Task{TResult}.Result"/>, use
|
||||
/// <c>RunOnFrameworkThread</c>.</li>
|
||||
/// </ul>
|
||||
/// <para>The game is likely to completely lock up if you call above synchronous function and getter, because starting
|
||||
/// a new task by default runs on <see cref="TaskScheduler.Current"/>, which would make the task run on the framework
|
||||
/// thread if invoked via <c>RunOnFrameworkThreadAwaitable</c>. This includes <c>Task.Factory.StartNew</c> and
|
||||
/// <c>Task.ContinueWith</c>. Use <c>Task.Run</c> if you need to start a new task from the callback specified to
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, as it will force your task to be run in the default thread pool.</para>
|
||||
/// <para>See <see cref="TaskSchedulerWidget"/> to see the difference in behaviors, and how would a misuse of these
|
||||
/// functions result in a deadlock.</para>
|
||||
/// </remarks>
|
||||
public interface IFramework
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -29,11 +47,6 @@ public interface IFramework
|
|||
/// </summary>
|
||||
public DateTime LastUpdateUTC { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="TaskFactory"/> that runs tasks during Framework Update event.
|
||||
/// </summary>
|
||||
public TaskFactory FrameworkThreadTaskFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the delta between the last Framework Update and the currently executing one.
|
||||
/// </summary>
|
||||
|
|
@ -49,20 +62,97 @@ public interface IFramework
|
|||
/// </summary>
|
||||
public bool IsFrameworkUnloading { get; }
|
||||
|
||||
/// <summary>Gets a <see cref="TaskFactory"/> that runs tasks during Framework Update event.</summary>
|
||||
/// <returns>The task factory.</returns>
|
||||
public TaskFactory GetTaskFactory();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a task that completes after the given number of ticks.
|
||||
/// </summary>
|
||||
/// <param name="numTicks">Number of ticks to delay.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A new <see cref="Task"/> that gets resolved after specified number of ticks happen.</returns>
|
||||
/// <remarks>The continuation will run on the framework thread by default.</remarks>
|
||||
public Task DelayTicks(long numTicks, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call.
|
||||
/// </summary>
|
||||
/// <param name="action">Function to call.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Starting new tasks and waiting on them <b>synchronously</b> from this callback will completely lock up
|
||||
/// the game. Use <c>await</c> if you need to wait on something from an <c>async</c> callback.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task RunOnFrameworkThreadAwaitable(Action action, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Return type.</typeparam>
|
||||
/// <param name="action">Function to call.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Starting new tasks and waiting on them <b>synchronously</b> from this callback will completely lock up
|
||||
/// the game. Use <c>await</c> if you need to wait on something from an <c>async</c> callback.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task<T> RunOnFrameworkThreadAwaitable<T>(Func<T> action, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call.
|
||||
/// </summary>
|
||||
/// <param name="action">Function to call.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Starting new tasks and waiting on them <b>synchronously</b> from this callback will completely lock up
|
||||
/// the game. Use <c>await</c> if you need to wait on something from an <c>async</c> callback.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task RunOnFrameworkThreadAwaitable(Func<Task> action, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Return type.</typeparam>
|
||||
/// <param name="action">Function to call.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Starting new tasks and waiting on them <b>synchronously</b> from this callback will completely lock up
|
||||
/// the game. Use <c>await</c> if you need to wait on something from an <c>async</c> callback.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task<T> RunOnFrameworkThreadAwaitable<T>(Func<Task<T>> action, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Return type.</typeparam>
|
||||
/// <param name="func">Function to call.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task<T> RunOnFrameworkThread<T>(Func<T> func);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -70,6 +160,16 @@ public interface IFramework
|
|||
/// </summary>
|
||||
/// <param name="action">Function to call.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task RunOnFrameworkThread(Action action);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -78,6 +178,16 @@ public interface IFramework
|
|||
/// <typeparam name="T">Return type.</typeparam>
|
||||
/// <param name="func">Function to call.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
[Obsolete($"Use {nameof(RunOnTick)} instead.")]
|
||||
public Task<T> RunOnFrameworkThread<T>(Func<Task<T>> func);
|
||||
|
||||
|
|
@ -86,6 +196,16 @@ public interface IFramework
|
|||
/// </summary>
|
||||
/// <param name="func">Function to call.</param>
|
||||
/// <returns>Task representing the pending or already completed function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
[Obsolete($"Use {nameof(RunOnTick)} instead.")]
|
||||
public Task RunOnFrameworkThread(Func<Task> func);
|
||||
|
||||
|
|
@ -98,6 +218,16 @@ public interface IFramework
|
|||
/// <param name="delayTicks">Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter.</param>
|
||||
/// <param name="cancellationToken">Cancellation token which will prevent the execution of this function if wait conditions are not met.</param>
|
||||
/// <returns>Task representing the pending function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task<T> RunOnTick<T>(Func<T> func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -108,6 +238,16 @@ public interface IFramework
|
|||
/// <param name="delayTicks">Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter.</param>
|
||||
/// <param name="cancellationToken">Cancellation token which will prevent the execution of this function if wait conditions are not met.</param>
|
||||
/// <returns>Task representing the pending function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task RunOnTick(Action action, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -119,6 +259,16 @@ public interface IFramework
|
|||
/// <param name="delayTicks">Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter.</param>
|
||||
/// <param name="cancellationToken">Cancellation token which will prevent the execution of this function if wait conditions are not met.</param>
|
||||
/// <returns>Task representing the pending function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task<T> RunOnTick<T>(Func<Task<T>> func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -129,5 +279,15 @@ public interface IFramework
|
|||
/// <param name="delayTicks">Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter.</param>
|
||||
/// <param name="cancellationToken">Cancellation token which will prevent the execution of this function if wait conditions are not met.</param>
|
||||
/// <returns>Task representing the pending function.</returns>
|
||||
/// <remarks>
|
||||
/// <para><c>await</c>, <c>Task.Factory.StartNew</c> or alike will continue off the framework thread.</para>
|
||||
/// <para>Awaiting on the returned <see cref="Task"/> from <c>RunOnFrameworkThread</c>,
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c>, or <c>RunOnTick</c> right away inside the callback specified to this
|
||||
/// function has a chance of locking up the game. Do not do <c>await framework.RunOnFrameworkThread(...);</c>
|
||||
/// directly or indirectly from the delegate passed to this function.</para>
|
||||
/// <para>See the remarks on <see cref="IFramework"/> if you need to choose which one to use, between
|
||||
/// <c>RunOnFrameworkThreadAwaitable</c> and <c>RunOnFrameworkThread</c>. Note that <c>RunOnTick</c> is a fancy
|
||||
/// version of <c>RunOnFrameworkThread</c>.</para>
|
||||
/// </remarks>
|
||||
public Task RunOnTick(Func<Task> func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue