Closed KoertLichtendonk closed 5 years ago
task_valid
returns false for the task then, doesn't it? If you use task_set_result
, it will invoke all registered continuations (i.e. paused calls to task_wait
) and then automatically delete the task, unless task_keep
is called (or task_reset
is called inside the continuation).
You can call task_keep
to prevent the task from being automatically collected, but you also need to call task_delete
in that case. I suggest you not to use a task at all, if you don't want need to wait for anything.
task_valid
returns true before task_set_result
in SelectPlayerFaction
under case 1:
is called, just checked it, but task_get_result
in /badge returns 0 when it's supposed to return 4.
task_valid
should return false after task_set_result
.
Yes it does, but I still should be able to use task_get_result
to get the result after a task has ended, correct? That's what currently does not work for me in this set-up.
This behaviour is intended; you should not be able to access the task once is has completed. Notice that your code doesn't delete the task at all, which is fine, since it gets deleted automatically at the point of task_set_result
. Otherwise, you would have to call task_delete
after it, but then there would be no mechanism for the continuation to extend the lifetime of the task.
Tasks are used to resume paused code; there is usually not much point in keeping the task alive after code that wanted to handle it ended. As I said, if you want to use tasks in a non-standard way (i.e. keeping it alive after its completion or just for storing a value), there is task_keep
which can be used any time to disable this autocollection.
new Task:t = task_new();
task_keep(t);
task_set_result(t, 1);
...
task_delete(t);
Ahh, I still believe I found a bug in that case which is the reason I got confused, because task_get_result did return 4 (the value I needed) when characters had multiple factions (meaning they would go through the dialog and once they selected their faction from the dialog the task_await code would continue) even though I had no task_keep on at that time.
It's clear now, thanks for your help.
In that case, the task will be available immediately in the continuation (i.e. after task_await
) but will be collected once the continuation exits (and the code after task_set_result
will then continue as usual).
So, what's the difference between task_set_result
in SelectPlayerFaction
and task_set_result
in the dialog (e.g. why does it work fine in the dialog, and not in the function)? Because that's my intended behavior, to return a faction ID and continue the task_await
. It works fine with task_keep
now but I'm curious because I don't really get the difference between both scenarios.
A call to task_await
registers a continuation in the task object. The continuation consists of the code that follows the call to task_await
up until the end of the callback.
In the first case, the order of operations is 1) task_set_result
, 2) task_await
. Since there is no continuation registered when you call task_set_result
, nothing will happen, and the task is collected (since it is completed and nothing can wait for it). Further calls are performed on a nonexistent task and thus return invalid values.
In the second case, task_await
is called first. This pauses the code, registers the continuation, and exits the callback. Calling task_set_result
then will restore the original code and call the continuation. This call actually happens entirely inside task_set_result
, so during its execution, the task is still alive. After all continuations are executed, the task is collected.
Using task_keep
in the first case prevents task_set_result
from deleting the task, so a call to task_await
returns immediately (the task is already completed). This way, you must use task_delete
to explicitly destroy the task, or you'll end up with a memory leak. You have no other option than to put it after task_await
, which is fine in the first case, but in the second case, it deletes the task in the middle of task_set_result
, which may potentially result in undefined behaviour. You should not call task_keep
and task_delete
in the second case.
Also note that task_await
is (at least in the latest version) a combination of task_wait
and task_get_result
. You can simplify your code to:
new memberSelected = task_awaitPlayerInfo[playerid][pAwaitMembershipSelection]);
Oh damn, thank you for your help, it's been really helpful to me. It seems like there's no way to call SelectPlayerFaction
after the continuation is registered, seeing as task_await
freezes the code until the task is finished. So I have no choice but to use task_keep
and task_delete
in both cases. I'll probably do some tests to see if it shows any 'undefined behavior' first.
I still think not creating a task when not needed is the best option, but to address your case, I have modified task_set_result
to prevent the task object from being destroyed inside a continuation. It will be more or less okay to delete it then (the task will be removed from the task pool, but the actual object will be kept alive until task_set_result
ends).
Hey there. I changed my old code a bit, in the old code I stored the ID in a seperate variable, now I instead pass the ID over task_set_result.
https://pastebin.com/pb4YWxGQ
When someone does the /badge command, it executes the SelectPlayerFaction function, which then checks how many factions the player is a member of. If there's only one faction, it should set the ID of that faction as the result. It does set a result, but for some reason it always sends back 0 to the command. I also printed out the value of Iter_First and it does print out the currect value. What is also odd, is that when a player is a member of multiple factions and he goes through the dialog and selects a faction, it does somehow work.
I've tried everything, there's no errors, warnings or anything strange in any of the logs. This is also all of my code in regards to the PlayerInfo[playerid][pAwaitMembershipSelection] task, so it's not being reset or something in the background. I even reverted back to the old style where I stored the information in a seperate variable, and that doesn't work either, leading me to think it has something to do with the "case 1" part I added inbetween, but there's nothing wrong there, so I'm legitimately confused.