❔ Any way to optimize this? Task.WhenAll

This takes anywhere from 6-14 seconds, Any way to make it faster?
private async Task HandlePhaseAudioFileStorage()
{
var tasks = new List<Task>();
foreach (var phase in _currentLesson.Phases)
{
// Generate default bot audio if not provided
if (phase.BotAudio is null)
{
phase.BotAudio = await _googleApiManager.TextToSpeechAsync(phase.BotText, _srcLanguageCode);
var defaultBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.DefaultPhaseBlobFileId = defaultBotBlobKey;
var botAudioWithTranslation = new AudioAndTranslation(phase.BotAudio, phase.BotText);
tasks.Add(_azureBlobStorageManager.SaveServerGeneratedFilesBytesAsync(defaultBotBlobKey,
botAudioWithTranslation));
}
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTask = phase.BotResponseAudioOnSuccess is not null
? Task.FromResult(phase.BotResponseAudioOnSuccess)
: _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

tasks.Add(botSuccessAudioTask.ContinueWith(async (botSuccessAudioTaskResult) =>
{
var botSuccessAudio = await botSuccessAudioTaskResult;
var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudio, phase.BotResponseTextOnSuccess);
await _azureBlobStorageManager.SaveServerGeneratedFilesBytesAsync(successBotBlobKey,
botSuccessAudioWithTranslation);
}));
}

}
}

await Task.WhenAll(tasks);
}
private async Task HandlePhaseAudioFileStorage()
{
var tasks = new List<Task>();
foreach (var phase in _currentLesson.Phases)
{
// Generate default bot audio if not provided
if (phase.BotAudio is null)
{
phase.BotAudio = await _googleApiManager.TextToSpeechAsync(phase.BotText, _srcLanguageCode);
var defaultBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.DefaultPhaseBlobFileId = defaultBotBlobKey;
var botAudioWithTranslation = new AudioAndTranslation(phase.BotAudio, phase.BotText);
tasks.Add(_azureBlobStorageManager.SaveServerGeneratedFilesBytesAsync(defaultBotBlobKey,
botAudioWithTranslation));
}
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTask = phase.BotResponseAudioOnSuccess is not null
? Task.FromResult(phase.BotResponseAudioOnSuccess)
: _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

tasks.Add(botSuccessAudioTask.ContinueWith(async (botSuccessAudioTaskResult) =>
{
var botSuccessAudio = await botSuccessAudioTaskResult;
var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudio, phase.BotResponseTextOnSuccess);
await _azureBlobStorageManager.SaveServerGeneratedFilesBytesAsync(successBotBlobKey,
botSuccessAudioWithTranslation);
}));
}

}
}

await Task.WhenAll(tasks);
}
71 Replies
Florian Voß
Florian Voß16mo ago
not sure if my suggestions will make it faster but some things I would give a try @AntiMatter : - try rewriting your code to use Parallel.ForEach() - await only when the result of the async operation is needed. You are awaiting everything directly which is not always needed, e.g. you await TextToSpeechAsync() before you do other operations even tho you need the result (phase.BotAudio) after those other operations, you can await it later when you really need the result. - maybe you can make sync work that you have async too? such as GenerateBlobKey(), try making that async
JakenVeina
JakenVeina16mo ago
private Task ProcessItemsInParallelAsync(IEnumerable<T> items)
=> Task.WhenAll(items
.Select(async item =>
{
...
}));
private Task ProcessItemsInParallelAsync(IEnumerable<T> items)
=> Task.WhenAll(items
.Select(async item =>
{
...
}));
if you're on .NET 6+, you also have access to Parallel.ForEachAsync() which gives you a few more under-the-hood mechanical optimizations, which might help if you have very large workloads
await Parallel.ForEachAsync(items,
async (item, cancellationToken) =>
{
...
});
await Parallel.ForEachAsync(items,
async (item, cancellationToken) =>
{
...
});
in your code, you're not actually running everything in parallel you've got an await in the first if block that forces some or all of those elements to serialize, instead of running in parallel
Florian Voß
Florian Voß16mo ago
@AnievNekaj what do you think bout my suggestions, are they good? if we do all three things: 1. parallelize 2. await later when result is needed 3. make sync work async too it should get a lot faster right?
antimatter8189
antimatter818916mo ago
Well what i ended up doing is what @AnievNekaj suggested with await Parallel.ForEachAsync(_currentLesson.Phases) cut it down to 3-4 secs I cant paste the entire methode here basically :
var tasks = new List<Task>();
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
{
// Generate default bot audio if not provided
if (phase.BotResponseTextOnSuccess is not null || phase.BotAudio is null)
{

if (phase.BotAudio is null)
{
var defaultBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.DefaultPhaseBlobFileId = defaultBotBlobKey;

tasks.Add(_googleApiManager.TextToSpeechAsync(phase.BotText, _srcLanguageCode).ContinueWith(
async (botAudioTaskResult) =>
{
phase.BotAudio = await botAudioTaskResult;
var botAudioWithTranslation = new AudioAndTranslation(phase.BotAudio, phase.BotText,
_currentLesson.Id, phase.PhaseNumber);
await _azureBlobStorageManager.SaveBotDefaultAudioContainer(defaultBotBlobKey,
botAudioWithTranslation);
}, cancellationToken));
}
}
var tasks = new List<Task>();
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
{
// Generate default bot audio if not provided
if (phase.BotResponseTextOnSuccess is not null || phase.BotAudio is null)
{

if (phase.BotAudio is null)
{
var defaultBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.DefaultPhaseBlobFileId = defaultBotBlobKey;

tasks.Add(_googleApiManager.TextToSpeechAsync(phase.BotText, _srcLanguageCode).ContinueWith(
async (botAudioTaskResult) =>
{
phase.BotAudio = await botAudioTaskResult;
var botAudioWithTranslation = new AudioAndTranslation(phase.BotAudio, phase.BotText,
_currentLesson.Id, phase.PhaseNumber);
await _azureBlobStorageManager.SaveBotDefaultAudioContainer(defaultBotBlobKey,
botAudioWithTranslation);
}, cancellationToken));
}
}
@Florian Voß anything else to add to this? Im using .net 7 btw
Florian Voß
Florian Voß16mo ago
looks much better now, you've fullfilled the first and second point I mentioned. Third is least important one, might potentially even make it slower
antimatter8189
antimatter818916mo ago
Thanks bud 😄 you too @AnievNekaj
Becquerel
Becquerel16mo ago
you may also want to look into using ValueTask since there are branches in this where async work is not done (phase.BotAudio is not null and phase.BotResponseTextOnSuccess is null) if the non-async path is the most common one then ValueTask will let it run synchronously, which can be a perf boost valuetask comes with a lot of gotchas though, and i don't remember even half of them, so read the docs before trying it
JakenVeina
JakenVeina16mo ago
Parallel.ForEachAsync() only supports ValueTask. And ValueTask is really only valuable for work that has a high likelihood of completing synchronously. This appears to be I/O work, which has no likelihood of completing synchronously.
antimatter8189
antimatter818915mo ago
I dont quit get that, You're saying Parallel.ForEachAsync() only supports ValueTask and thats no good for I/O work, but thats what i've implemented and it did cut down time
JakenVeina
JakenVeina15mo ago
nono, I mean the advantage of using ValueTask over Task is when the majority of them will be already-complete upon creation, I.E. you ended up not having any asynchronous work to do. In this scenario, ValueTask avoids all the memory allocations that are associated with using a Task, regardless of whether it completes immediately. You're seeing benefit because you weren't properly parallelizing before, not because you're using ValueTasks. Which you might not be using, anyway. I'm not sure what the rules are for anonymous async methods, regarding when they return ValueTask instead of Task, or if that's even a thing at all. I believe Task can be implicitly cast to ValueTask, so just because Parallel.ForEachAsync() only accepts ValueTask, that doesn't necessarily mean that your async method is returning one.
antimatter8189
antimatter818915mo ago
Gotcha another small question
async (phase, cancellationToken) =>
async (phase, cancellationToken) =>
Tells me its async void basically cuz no await inside any way to mitigate it? @AnievNekaj the await only happens in certain scopes
JakenVeina
JakenVeina15mo ago
if there's no await in the method, don't make it async
antimatter8189
antimatter818915mo ago
yeah then i cant use ContinueWith in the inner IF scopes, lol odd stuff Is this warning even solvable
JakenVeina
JakenVeina15mo ago
incorrect also, there is no reason for you to be using .ContinueWith()
antimatter8189
antimatter818915mo ago
How so?
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTask = phase.BotResponseAudioOnSuccess is not null
? Task.FromResult(phase.BotResponseAudioOnSuccess)
: _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

tasks.Add(botSuccessAudioTask.ContinueWith(async (botSuccessAudioTaskResult) =>
{
var botSuccessAudio = await botSuccessAudioTaskResult;
var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudio, phase.BotResponseTextOnSuccess, _currentLesson.Id,
phase.PhaseNumber);
await _azureBlobStorageManager.SaveBotSuccessContainer(successBotBlobKey,
botSuccessAudioWithTranslation);
}, cancellationToken));
}
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTask = phase.BotResponseAudioOnSuccess is not null
? Task.FromResult(phase.BotResponseAudioOnSuccess)
: _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

tasks.Add(botSuccessAudioTask.ContinueWith(async (botSuccessAudioTaskResult) =>
{
var botSuccessAudio = await botSuccessAudioTaskResult;
var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudio, phase.BotResponseTextOnSuccess, _currentLesson.Id,
phase.PhaseNumber);
await _azureBlobStorageManager.SaveBotSuccessContainer(successBotBlobKey,
botSuccessAudioWithTranslation);
}, cancellationToken));
}
I need the bot audio to save to the blob storage I need the api call to finish before i pass it to be saved
JakenVeina
JakenVeina15mo ago
because that's what await is for
antimatter8189
antimatter818915mo ago
I do have this
var botSuccessAudio = await botSuccessAudioTaskResult;
var botSuccessAudio = await botSuccessAudioTaskResult;
JakenVeina
JakenVeina15mo ago
right do that
antimatter8189
antimatter818915mo ago
hm? this is the first time im using continueWith btw
JakenVeina
JakenVeina15mo ago
and the last
antimatter8189
antimatter818915mo ago
Can u elaborate or provide some small code so i can undestand what im doing wrong
JakenVeina
JakenVeina15mo ago
unless you are a framework author, you have no reason to use .ContinueWith() what is the async work you need to do
antimatter8189
antimatter818915mo ago
Well get audio from an api and save it to the blob depending on if text is null
JakenVeina
JakenVeina15mo ago
okay, the first part of that what is the code to do that?
gerard
gerard15mo ago
.ContinueWith is from .NET Framework 4.0, when async/await wasn't a thing Sweats
antimatter8189
antimatter818915mo ago
ehh its hard with partial code
antimatter8189
antimatter818915mo ago
Pastebin
private async Task HandlePhaseAudioFileStorage() { var t...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
JakenVeina
JakenVeina15mo ago
and it is, quite literally, what await does, just cleaner
antimatter8189
antimatter818915mo ago
I want to optimize this as much as i can cuz its a choke point atm
JakenVeina
JakenVeina15mo ago
yeah, I was unable to read your snippets on mpbipe already *mobile
antimatter8189
antimatter818915mo ago
This is the full methode not that long about 60 lines anways Wtf do i need to do, give me a specific step or w/e lol
JakenVeina
JakenVeina15mo ago
you said it yourself, you need to retrieve audio from an API
antimatter8189
antimatter818915mo ago
Lol oh rly
JakenVeina
JakenVeina15mo ago
var audio = await Api.GetAudioAsync();
var audio = await Api.GetAudioAsync();
then save it to a blob
await blob.SaveAudioAsync(audio);
await blob.SaveAudioAsync(audio);
and you had some kinda condition for doing this
gerard
gerard15mo ago
And remove the tasks list. You're currently adding everything to a list in Parallel.ForEachAsync without awaiting anything. This defeats the purpose of this method.
JakenVeina
JakenVeina15mo ago
if (condition)
{
var audio = await Api.GetAudioAsync();
await blob.SaveAudioAsync(audio);
}
if (condition)
{
var audio = await Api.GetAudioAsync();
await blob.SaveAudioAsync(audio);
}
gerard
gerard15mo ago
Either use Task.WhenAll or Parallel.ForEachAsync
antimatter8189
antimatter818915mo ago
so
JakenVeina
JakenVeina15mo ago
yes, we've already been over that
antimatter8189
antimatter818915mo ago
smth like this
// Generate bot response audio on success if provided
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTaskResult = phase.BotResponseAudioOnSuccess is not null
? phase.BotResponseAudioOnSuccess
: await _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudioTaskResult, phase.BotResponseTextOnSuccess, _currentLesson.Id,
phase.PhaseNumber);
tasks.Add(_azureBlobStorageManager.SaveBotSuccessContainer(successBotBlobKey,
botSuccessAudioWithTranslation));
}
// Generate bot response audio on success if provided
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTaskResult = phase.BotResponseAudioOnSuccess is not null
? phase.BotResponseAudioOnSuccess
: await _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudioTaskResult, phase.BotResponseTextOnSuccess, _currentLesson.Id,
phase.PhaseNumber);
tasks.Add(_azureBlobStorageManager.SaveBotSuccessContainer(successBotBlobKey,
botSuccessAudioWithTranslation));
}
JakenVeina
JakenVeina15mo ago
going back to my original example
antimatter8189
antimatter818915mo ago
Yey we got there bois
JakenVeina
JakenVeina15mo ago
await Parallel.ForEachAsync(items,
async (item, cancellationToken) =>
{
...
});
await Parallel.ForEachAsync(items,
async (item, cancellationToken) =>
{
...
});
antimatter8189
antimatter818915mo ago
hm yeah i remember that one
JakenVeina
JakenVeina15mo ago
whatever async work you need to do for each item goes where the ... is just write declarative code like you normally would except, anything that returns a Task, you await that's it
antimatter8189
antimatter818915mo ago
Gotcha bud, thx alot!
JakenVeina
JakenVeina15mo ago
if you want further context, write out this async method you need, with whatever awaits and if blocks and logic you need then compile it and go take a look at what the compiler generates, with ILSpy
antimatter8189
antimatter818915mo ago
well i got to this:
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
{
async Task SaveDefaultBotAudio()
{
var defaultBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.DefaultPhaseBlobFileId = defaultBotBlobKey;

var botAudio = await _googleApiManager.TextToSpeechAsync(phase.BotText, _srcLanguageCode);
var botAudioWithTranslation = new AudioAndTranslation(botAudio, phase.BotText,
_currentLesson.Id, phase.PhaseNumber);

await _azureBlobStorageManager.SaveBotDefaultAudioContainer(defaultBotBlobKey,
botAudioWithTranslation);
}
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
{
async Task SaveDefaultBotAudio()
{
var defaultBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.DefaultPhaseBlobFileId = defaultBotBlobKey;

var botAudio = await _googleApiManager.TextToSpeechAsync(phase.BotText, _srcLanguageCode);
var botAudioWithTranslation = new AudioAndTranslation(botAudio, phase.BotText,
_currentLesson.Id, phase.PhaseNumber);

await _azureBlobStorageManager.SaveBotDefaultAudioContainer(defaultBotBlobKey,
botAudioWithTranslation);
}
and each task like this i add to the list and execute them all at the end
JakenVeina
JakenVeina15mo ago
alternatively, you can see decompilations with sharplab.io
antimatter8189
antimatter818915mo ago
Yeah ik them tools, i think its built in rider which im using
JakenVeina
JakenVeina15mo ago
again, I really cannot read that on mobile is that a private function inside the anonymous delegate? SaveDefaultBotAudio()?
antimatter8189
antimatter818915mo ago
ahh shit smth broke i dont get the audio files back now
async Task SaveDefaultBotAudio()
async Task SaveDefaultBotAudio()
JakenVeina
JakenVeina15mo ago
yeah
antimatter8189
antimatter818915mo ago
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
{
async Task SaveDefaultBotAudio()
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
{
async Task SaveDefaultBotAudio()
`
JakenVeina
JakenVeina15mo ago
what's the purpose of that?
antimatter8189
antimatter818915mo ago
Idk i though it would be faster/efficient I guess i need to go read more about async/await I;ll be back here tomorrow with insights.
JakenVeina
JakenVeina15mo ago
it would be faster to declare a reusable function that isn't reused anywhere else? or is it?
antimatter8189
antimatter818915mo ago
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTaskResult = phase.BotResponseAudioOnSuccess is not null
? phase.BotResponseAudioOnSuccess
: await _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudioTaskResult, phase.BotResponseTextOnSuccess, _currentLesson.Id,
phase.PhaseNumber);
tasks.Add(_azureBlobStorageManager.SaveBotSuccessContainer(successBotBlobKey,
botSuccessAudioWithTranslation));
}
if (phase.BotResponseTextOnSuccess is not null)
{
var successBotBlobKey = _azureBlobStorageManager.GenerateBlobKey();
phase.SuccessPhaseBlobFileId = successBotBlobKey;

var botSuccessAudioTaskResult = phase.BotResponseAudioOnSuccess is not null
? phase.BotResponseAudioOnSuccess
: await _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);

var botSuccessAudioWithTranslation =
new AudioAndTranslation(botSuccessAudioTaskResult, phase.BotResponseTextOnSuccess, _currentLesson.Id,
phase.PhaseNumber);
tasks.Add(_azureBlobStorageManager.SaveBotSuccessContainer(successBotBlobKey,
botSuccessAudioWithTranslation));
}
This works and kinda is fast so gonna keep it like that for now the azure tasks get sent all together the other ones i await
JakenVeina
JakenVeina15mo ago
they get sent all together?
antimatter8189
antimatter818915mo ago
Its only used once Well smth is working right since before it used to take 10-14 secs now its 4-6
JakenVeina
JakenVeina15mo ago
yeah, the parallelism is probably the bulk of that you're now starting all of the google API calls at basically the same time and each time one of them returns, you immediately follow up with the next step (if any)
antimatter8189
antimatter818915mo ago
so each
: await _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);
: await _googleApiManager.TextToSpeechAsync(phase.BotResponseTextOnSuccess, _srcLanguageCode);
gets a new thread? and executes on it? then comes back to the azure blob save logic? thats the flow?
JakenVeina
JakenVeina15mo ago
threads aren't even really a concern here maybe, maybe not, depends on how Parallel.ForEachAsync() schedules things
antimatter8189
antimatter818915mo ago
How does it work, it awaits the google api, then adds a task to do smth with the result no? then all them tasks in the list that are purely related to blobstorage get executed together
JakenVeina
JakenVeina15mo ago
each execution of the async delegate is its own "logical" thread
antimatter8189
antimatter818915mo ago
but becuse of this
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
await Parallel.ForEachAsync(_currentLesson.Phases,
async (phase, cancellationToken) =>
all the await tasks get sent together Im getting this correct?
JakenVeina
JakenVeina15mo ago
yes, it terms of what you're trying to say, but no in terms of what's actually happening I'm happy to descibe what's going on in more detail, but I'm about to be on the road for 6 hours
antimatter8189
antimatter818915mo ago
I'll appreciate if when u come back you can dive in its interesting
JakenVeina
JakenVeina15mo ago
you can also go read up on how async/await works, mechanically
antimatter8189
antimatter818915mo ago
Im going off for today also Ik it creates a state machine etc i saw the nick chapsas videos Anyways thx for today bud! gn and thanks again
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts
❔ Delayed call to a functionI am writing search in Blazor and the search needs to happen without enter or tab press. What I wan❔ [MVC/RazorPages] Why can't I access model data?If I try printing to console the form data that I've `[BindProperty] ` on the OnPost() method, it co❔ async void in event handler (window "OnClosing" event)I have this code here which obviously shouldn't work due to how async void and Task.Delay naturally ❔ trying to get my Dialog system to be with a key press and not just walking into the npc, unity 2dI've been trying for awhile now to make it so it works but, everything I do doesn't work. I have a❔ Differenct action names is not working ASP.NET Corehttps://stackoverflow.com/questions/76006309/different-action-names-are-not-working-in-asp-net-core-❔ how to deploy asp.net project to ec2 linux server using github actions with dockerHi guys i want to deploy my api project (.net 6) to ec2 server (linux) with github actions and it wi❔ WPF Date entry Forms MVVMHello, I don't understand in WPF when I should use MVVM and when I shouldn't. For example, i'm loadi❔ Access appsettings.json in ASP.NET Web API in Azure published App Servicehttps://stackoverflow.com/questions/76005641/azure-hosted-asp-net-web-api-cannot-access-appsettings-❔ Akka.net Actors are not responding in timeI have a system that consists of two Actor classes and a class that calls these actors. ```cs publi✅ DialogResult and MessageBox in class (namespace)Hi, I have a class library and wanted to know if its possible to add a dialog result and message box