C
C#2w ago
hugeman

Global variable that only exists during initial call + async continuations

Hey so in my app I have a transition from void to async. During the initial call to the async part (the synchronous part) and all continuations, I want to be able to set a global variable, and only for continuations that originate from that original call. This is so that I can associate different globals to the same async call. The void to async part also happens on my app's main thread, and continuations ofc only run on the main thread. Is there a way to do this?
3 Replies
hugeman
hugemanOP2w ago
For example:
internal static void OnUserInputEvent(Window window, Control control, InputEvent e)
{
CurrentWindow = window;
CurrentControl = control;

List<Command> commands = ... // get list of commands to run based on input event
foreach (var command in commands)
command.ExecuteAsync();

CurrentWindow = null;
CurrentControl = null;
}

public void OpenFileCommand : Command
{
public async Task ExecuteAsync() {
string? path = IFileSystemService.Instance.ShowOpenFileDialog();
// ... do stuff with path
}
}
internal static void OnUserInputEvent(Window window, Control control, InputEvent e)
{
CurrentWindow = window;
CurrentControl = control;

List<Command> commands = ... // get list of commands to run based on input event
foreach (var command in commands)
command.ExecuteAsync();

CurrentWindow = null;
CurrentControl = null;
}

public void OpenFileCommand : Command
{
public async Task ExecuteAsync() {
string? path = IFileSystemService.Instance.ShowOpenFileDialog();
// ... do stuff with path
}
}
ShowOpenFileDialog would access the current CurrentWindow so that it can be shown as a modal dialog But if some work gets done or someone does Task.Delay before showing the file dialog, then CurrentWindow will be reset to null That seems to work nice It actually works perfectly i didn't expect it to work at all
DataKey<int> testKey = DataKey<int>.Create("cool test");
_ = Task.Run(() => Instance.Dispatcher.Post(() => _ = RunFunThings(new ContextData().Set(testKey, 1))));
await Task.Delay(100);
_ = Task.Run(() => Instance.Dispatcher.Post(() => _ = RunFunThings(new ContextData().Set(testKey, 2))));
DataKey<int> testKey = DataKey<int>.Create("cool test");
_ = Task.Run(() => Instance.Dispatcher.Post(() => _ = RunFunThings(new ContextData().Set(testKey, 1))));
await Task.Delay(100);
_ = Task.Run(() => Instance.Dispatcher.Post(() => _ = RunFunThings(new ContextData().Set(testKey, 2))));
private static async Task RunFunThings(IContextData context) {
using IDisposable usage = CommandManager.LocalContextManager.PushGlobalContext(context);
await Task.Delay(1000);

bool found = CommandManager.LocalContextManager.TryGetGlobalContext(out IContextData? localContext);
Debug.Assert(found && localContext == context);
}
private static async Task RunFunThings(IContextData context) {
using IDisposable usage = CommandManager.LocalContextManager.PushGlobalContext(context);
await Task.Delay(1000);

bool found = CommandManager.LocalContextManager.TryGetGlobalContext(out IContextData? localContext);
Debug.Assert(found && localContext == context);
}
Code doesn't fail at all
Jose Rizal
Jose Rizal2w ago
use AsyncLocal<T> to flow a contextual value across the async call and its continuations on the main thread, so each original invocation carries its own associated global
Unknown User
Unknown User2w ago
Message Not Public
Sign In & Join Server To View

Did you find this page helpful?