C
C#2y ago
Boggo

❔ multiple Async responses

So im trying to use async for the first time, i am making a few api requests one after the other, the issue is that the order gets mixed up since the requests are being made asynchronously. I need a way of ensuring the order is enforced
61 Replies
jcotton42
jcotton422y ago
wdym "order gets mixed up"? can you show the $code, and say what you're expecting to happen? (and what's actually happening)
MODiX
MODiX2y ago
To post C# code type the following: ```cs // code here ``` Get an example by typing $codegif in chat If your code is too long, post it to: https://paste.mod.gg/
Boggo
BoggoOP2y ago
its messy, but sure
private void FillMessages()
{
var messages = _db.GetTextMsgsByServerId(_currServer.ServerId);
while (messages.Count > 0)
{
var message = messages.Pop();
DisplayNewMessage(message);
}
}
private void FillMessages()
{
var messages = _db.GetTextMsgsByServerId(_currServer.ServerId);
while (messages.Count > 0)
{
var message = messages.Pop();
DisplayNewMessage(message);
}
}
this gets messages from the database, then displays each one in turn theres some catches below shit wrong bit
Angius
Angius2y ago
Nothing here is async so far
Doombox
Doombox2y ago
was about to say, but my name could come in handy soon sunglas
Boggo
BoggoOP2y ago
private async void DisplayNewMessage(TextMessage message)
{
if (message == null)
{
MessageBox.Show("empty message");
return;
}

var settings = UserSettings.Load();
if (settings.LanguageCode != null)
{
var http = new HttpClient();
var response = await Task.Run(() => http.GetStringAsync($"myapi").Result);
response = response.Substring(17, response.Length - 19); //removes response information causing error converting to JObject
var translatedMsg = JObject.Parse(response);
var output = translatedMsg["text"]?.ToString();

MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {output}");
});
return;
}
MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {message.Content}");
});
}
private async void DisplayNewMessage(TextMessage message)
{
if (message == null)
{
MessageBox.Show("empty message");
return;
}

var settings = UserSettings.Load();
if (settings.LanguageCode != null)
{
var http = new HttpClient();
var response = await Task.Run(() => http.GetStringAsync($"myapi").Result);
response = response.Substring(17, response.Length - 19); //removes response information causing error converting to JObject
var translatedMsg = JObject.Parse(response);
var output = translatedMsg["text"]?.ToString();

MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {output}");
});
return;
}
MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {message.Content}");
});
}
Angius
Angius2y ago
Nothing async yet Well, async void
jcotton42
jcotton422y ago
var response = await Task.Run(() => http.GetStringAsync($"myapi").Result);
that's not async
Boggo
BoggoOP2y ago
var response
Angius
Angius2y ago
And await Task.Run() for some reason
jcotton42
jcotton422y ago
just await GetStringAsync directly
Boggo
BoggoOP2y ago
no task?
Angius
Angius2y ago
This is a doozy of a line lmao
Doombox
Doombox2y ago
why would you wrap an awaitable tasks .Result in task.run
jcotton42
jcotton422y ago
Task.Run is for shunting CPU-bound work to the thread pool
Doombox
Doombox2y ago
pepetense
Angius
Angius2y ago
It's an awaited task that runs an asynchronous method in a blocking, non-asynchronous context lol
jcotton42
jcotton422y ago
it is unnecessary here
Boggo
BoggoOP2y ago
my friend said the same thing but wasnt sure how to explain so ive come here
jcotton42
jcotton422y ago
the use of .Result is also completely wrong
Angius
Angius2y ago
You're stripping the asynchronicity away with that .Result then you add it back with Task.Run() A zero sum
jcotton42
jcotton422y ago
in any case, you mentioned multiple requests, but I only see the one
Doombox
Doombox2y ago
.GetAwaiter().GetResult() if you're going to make an asynchronous method call synchronous by the way, for future reference never .Result
jcotton42
jcotton422y ago
oh I see, multiple calls to DisplayNewMessage
Boggo
BoggoOP2y ago
first part of the code i sent
Angius
Angius2y ago
DisplayMessage() should be async Task first of all
jcotton42
jcotton422y ago
in any case, just because you send multiple requests in a given order, doesn't mean they'll return in that order
Boggo
BoggoOP2y ago
thats the issue^ if i cant, ill have to run without async, which i think would be terrible
jcotton42
jcotton422y ago
if you want them in parallel, you'll just have to deal with that
Angius
Angius2y ago
I mean,
var stuff = new List<int>();
stuff.Add(await GetIntAsync());
stuff.Add(await GetIntAsync());
stuff.Add(await GetIntAsync());
var stuff = new List<int>();
stuff.Add(await GetIntAsync());
stuff.Add(await GetIntAsync());
stuff.Add(await GetIntAsync());
will ensure the order
jcotton42
jcotton422y ago
you could queue up the responses somehow, and then run through that queue
Angius
Angius2y ago
Since one call will wait for another
jcotton42
jcotton422y ago
true
Boggo
BoggoOP2y ago
would it work, to get all the responses, without adding them to the UI display, and sort them by the "dateSent" property they have
jcotton42
jcotton422y ago
yes
Boggo
BoggoOP2y ago
then add them all that would work? or this
Angius
Angius2y ago
As long as at no point do you have async void, it'll be fine Because only Task can be awaited
Boggo
BoggoOP2y ago
var response = await http.GetStringAsync($"myapi"); oh how do you do your slightly dark background?
Angius
Angius2y ago
`code here`
Boggo
BoggoOP2y ago
gotcha ty this here requires private async void
jcotton42
jcotton422y ago
no it doesn't use async Task async Task is the async version of void you should only use async void when you have to
Angius
Angius2y ago
T => async Task<T> int => async Task<int> void => async Task
Boggo
BoggoOP2y ago
ok i see i think its a little better now, going to try the sorting thing i had
Angius
Angius2y ago
void is nothing. Nothing cannot be awaited, cannot be cancelled, cannot be queued... because it doesn't exist. So you need a something, a Task is that something
Boggo
BoggoOP2y ago
that makes a lot of sense, until now void was just "doesnt return anything"
jcotton42
jcotton422y ago
it still is
Boggo
BoggoOP2y ago
which is still true, just very vague ^^yup well thanks guys, had some input from everyone which was nice :)) until next time trying to use this, once the code hits the await get async part, it stops executing and returns to the UI as it seems
Angius
Angius2y ago
Ah, you're using WPF or some such?
Boggo
BoggoOP2y ago
winforms
Angius
Angius2y ago
Uh, yeah, at some point you'd need to use... what was it, Dispatcher.Invoke() or something? I don't have much experience with GUI frameworks
Boggo
BoggoOP2y ago
hm ok, it was working fine before, with the same api request code from within one Task, can i make multiple api requests?
Angius
Angius2y ago
Sure
Boggo
BoggoOP2y ago
this does not work
private async Task<List<TextMessage>> TranslateMessages(Stack<TextMessage> messages)
{
var orderedMsgs = new List<TextMessage>();
var settings = UserSettings.Load();


while (messages.Count > 0)
{
var message = messages.Pop();
var http = new HttpClient();
var response = await http.GetStringAsync($"myapi");
response = response.Substring(17, response.Length - 19); //removes response information causing error converting to JObject
var translatedMsg = JObject.Parse(response);
message.Content translatedMsg["text"]?.ToString();
orderedMsgs.Add(message);
}
return orderedMsgs;
}
private async Task<List<TextMessage>> TranslateMessages(Stack<TextMessage> messages)
{
var orderedMsgs = new List<TextMessage>();
var settings = UserSettings.Load();


while (messages.Count > 0)
{
var message = messages.Pop();
var http = new HttpClient();
var response = await http.GetStringAsync($"myapi");
response = response.Substring(17, response.Length - 19); //removes response information causing error converting to JObject
var translatedMsg = JObject.Parse(response);
message.Content translatedMsg["text"]?.ToString();
orderedMsgs.Add(message);
}
return orderedMsgs;
}
this will work, just not in order
private async Task DisplayNewMessage(TextMessage message)
{
if (message == null)
{
MessageBox.Show("empty message");
return;
}

var settings = UserSettings.Load();
if (settings.LanguageCode != null)
{
var http = new HttpClient();
var response = await http.GetStringAsync($"myapi");
response = response.Substring(17, response.Length - 19); //removes response information causing error converting to JObject
var translatedMsg = JObject.Parse(response);
var output = translatedMsg["text"]?.ToString();

MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {output}");
});
return;
}
MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {message.Content}");
});
}
private async Task DisplayNewMessage(TextMessage message)
{
if (message == null)
{
MessageBox.Show("empty message");
return;
}

var settings = UserSettings.Load();
if (settings.LanguageCode != null)
{
var http = new HttpClient();
var response = await http.GetStringAsync($"myapi");
response = response.Substring(17, response.Length - 19); //removes response information causing error converting to JObject
var translatedMsg = JObject.Parse(response);
var output = translatedMsg["text"]?.ToString();

MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {output}");
});
return;
}
MessagesLB.Invoke((MethodInvoker)delegate
{
MessagesLB.Items.Add($"{_db.GetClient(message.FromUser).UserName}: {message.Content}");
});
}
the http request is the same
Angius
Angius2y ago
Don't instantiate a new client with each loop iteration
Boggo
BoggoOP2y ago
ah i had it above actually, i moved it inside to check since thats what the second version is effectively doing
Angius
Angius2y ago
Yeah, idk, As I said, I'm not the best at desktop stuff, let alone Winforms @jcotton42 might know more?
Boggo
BoggoOP2y ago
all good, appreciate the time regardless, just threw it in here hoping someone might stumble across it again
jcotton42
jcotton422y ago
anyControl.Invoke iirc
Boggo
BoggoOP2y ago
im unsure what that means
jcotton42
jcotton422y ago
the Invoke method on any control like someTextBox.Invoke, someCheckBox.Invoke etc.
Accord
Accord2y 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