CounterStrikeSharp icon indicating copy to clipboard operation
CounterStrikeSharp copied to clipboard

Server.NextFrame not fire

Open daffyyyy opened this issue 4 months ago β€’ 34 comments

Hi, after the latest game/css updates, Server.NextFrame/Async often stops working when there are many players/hours. Switching to Server.NextWorldUpdate/Async or directly calling Action without returning to the main thread helps. These methods also do not work when executed from the main thread.

https://discord.com/channels/1160907911501991946/1160907912445710482/1406736574321922170 - reference

daffyyyy avatar Aug 19 '25 20:08 daffyyyy

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

KillStr3aK avatar Aug 19 '25 21:08 KillStr3aK

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

daffyyyy avatar Aug 19 '25 22:08 daffyyyy

Client #1 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:55462
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Player 🦊 daffyy | UtopiaFPS.pl 🦊 connected <--- only once
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #1 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:53722
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #1 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:53825
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #1 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:56189
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
			RegisterEventHandler((EventPlayerConnectFull @event, GameEventInfo info) =>
			{
				CCSPlayerController? player = @event.Userid;
				if (player == null || !player.IsValid)
					return HookResult.Continue;


				Server.NextFrame(() => Console.WriteLine($"Player {player.PlayerName} connected"));
				return HookResult.Continue;
			}

As you can see, nextframe print console message only once

Added additional message to check if player pass first if about null & valid

Client #1 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:55093
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Test passed
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #1 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:55285
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Test passed

But nextframe never fired

For comparison smaller server (fewer players per day, first server - 31 slot, second server - 20 slot)

Client #4 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:52029
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Player 🦊 daffyy | UtopiaFPS.pl 🦊 connected
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #4 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:50097
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Player 🦊 daffyy | UtopiaFPS.pl 🦊 connected
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #4 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:62619
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Player 🦊 daffyy | UtopiaFPS.pl 🦊 connected
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #4 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:54509
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
Player 🦊 daffyy | UtopiaFPS.pl 🦊 connected

always fired

[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
01:48:47 [INFO] (plugin:My Plugin) Good
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #22 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:57501
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
01:48:54 [INFO] (plugin:My Plugin) Good
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #22 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:65296
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0
01:49:02 [INFO] (plugin:My Plugin) Good
Netchan '🦊 daffyy | UtopiaFPS.pl 🦊' closed unexpectedly: NETWORK_DISCONNECT_LOOPDEACTIVATE
Disconnect client '🦊 daffyy | UtopiaFPS.pl 🦊' from server: NETWORK_DISCONNECT_LOOPDEACTIVATE
Client #22 "🦊 daffyy | UtopiaFPS.pl 🦊" connected @ IP:57756
[🦊 daffyy | UtopiaFPS.pl 🦊] cl_interp_ratio='0', LerpTime=0

It worked three times, but not the fourth

daffyyyy avatar Aug 19 '25 23:08 daffyyyy

Do you both are using pterodacyl with steamrt image?

Prefix avatar Aug 20 '25 04:08 Prefix

Do you both are using pterodacyl with steamrt image?

Yes Of course, I want to point out that before these updates everything worked

daffyyyy avatar Aug 20 '25 04:08 daffyyyy

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

KillStr3aK avatar Aug 20 '25 07:08 KillStr3aK

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

daffyyyy avatar Aug 20 '25 07:08 daffyyyy

Your sample code is not a valid reproduction, it mixes async flow incorrectly and schedules work from a context where the player may already be disconnected or invalid by the time the NextFrame action runs. That’s why you β€œsometimes” see nothing happening.

This isn’t an engine or framework bug. The behavior you see is because your lambda never executes due to object lifetime (player/controller already invalid) or misuse of async/await in the event context.

For me everything is working fine

Mesharsky avatar Aug 20 '25 09:08 Mesharsky

Your sample code is not a valid reproduction, it mixes async flow incorrectly and schedules work from a context where the player may already be disconnected or invalid by the time the NextFrame action runs. That’s why you β€œsometimes” see nothing happening.

This isn’t an engine or framework bug. The behavior you see is because your lambda never executes due to object lifetime (player/controller already invalid) or misuse of async/await in the event context.

For me everything is working fine

First - dont act like a child and discredit me at every turn, which is evident from your reactions. Second - https://discord.com/channels/1160907911501991946/1160907912445710482/1407649157266800721 tell to him too ;) and for third - im not passing controller to nextframe but my object ;) and fourthly, do you know why you never see any problems? Because you never have any players.

daffyyyy avatar Aug 20 '25 09:08 daffyyyy

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect

however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all)

instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option)

this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

KillStr3aK avatar Aug 20 '25 09:08 KillStr3aK

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect

however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all)

instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option)

this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

its a large plugin that is no longer supported by its author, but many people still use it, so we should find a way to fix it because, as you can see, many people mention it.

daffyyyy avatar Aug 20 '25 09:08 daffyyyy

Same issue with OnGameServerSteamAPIActivated listener, no longer fired on server startup - it behaves as if the server were in hibernation, but it is not.

daffyyyy avatar Aug 20 '25 09:08 daffyyyy

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect

however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all)

instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option)

this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

Again, the Player object is not a controller

I would also like to add that sometimes there are problems with mysql pooling, and connections used are never released. This has never happened before.

daffyyyy avatar Aug 20 '25 09:08 daffyyyy

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all) instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option) this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

Again, the Player object is not a controller

I would also like to add that sometimes there are problems with mysql pooling, and connections used are never released. This has never happened before.

I see that you use a custom player type in the async method, but not in the event handler

Image

Same issue with OnGameServerSteamAPIActivated listener, no longer fired on server startup - it behaves as if the server were in hibernation, but it is not.

the framework calls the listener when the game calls the given method, not sure if the game has changed something, or if we are refering to the wrong virtual func as there were many sdk changes

KillStr3aK avatar Aug 20 '25 09:08 KillStr3aK

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

the code is not deterministic because you are calling nextframe, anything could happen between the 2 calls

KillStr3aK avatar Aug 20 '25 09:08 KillStr3aK

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all) instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option) this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

Again, the Player object is not a controller I would also like to add that sometimes there are problems with mysql pooling, and connections used are never released. This has never happened before.

I see that you use a custom player type in the async method, but not in the event handler

Image > Same issue with OnGameServerSteamAPIActivated listener, no longer fired on server startup - it behaves as if the server were in hibernation, but it is not.

the framework calls the listener when the game calls the given method, not sure if the game has changed something, or if we are refering to the wrong virtual func as there were many sdk changes

				CCSPlayerController? player = @event.Userid;
				if (player == null || !player.IsValid)
					return HookResult.Continue;

				Logger.LogInformation("Always fire");
				Server.NextFrame(() => Console.WriteLine("Sometimes yes sometimes no"));

I can always access to controller, but problem is only with nextframe, because regardless of what i pass here, it often does not fire

daffyyyy avatar Aug 20 '25 09:08 daffyyyy

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all) instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option) this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

Again, the Player object is not a controller I would also like to add that sometimes there are problems with mysql pooling, and connections used are never released. This has never happened before.

I see that you use a custom player type in the async method, but not in the event handler Image

Same issue with OnGameServerSteamAPIActivated listener, no longer fired on server startup - it behaves as if the server were in hibernation, but it is not. the framework calls the listener when the game calls the given method, not sure if the game has changed something, or if we are refering to the wrong virtual func as there were many sdk changes

				CCSPlayerController? player = @event.Userid;
				if (player == null || !player.IsValid)
					return HookResult.Continue;

				Logger.LogInformation("Always fire");
				Server.NextFrame(() => Console.WriteLine("Sometimes yes sometimes no"));

I can always access to controller, but problem is only with nextframe, because regardless of what i pass here, it often does not fire

I can always access to controller

but you should not. event pointers are released after the callbacks are fired and its not guaranteed that you can still access anything. out of the many reasons this is one of them why we dont have/support async event handlers at the moment.

KillStr3aK avatar Aug 20 '25 09:08 KillStr3aK

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all) instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option) this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

Again, the Player object is not a controller I would also like to add that sometimes there are problems with mysql pooling, and connections used are never released. This has never happened before.

I see that you use a custom player type in the async method, but not in the event handler Image

Same issue with OnGameServerSteamAPIActivated listener, no longer fired on server startup - it behaves as if the server were in hibernation, but it is not. the framework calls the listener when the game calls the given method, not sure if the game has changed something, or if we are refering to the wrong virtual func as there were many sdk changes

				CCSPlayerController? player = @event.Userid;
				if (player == null || !player.IsValid)
					return HookResult.Continue;

				Logger.LogInformation("Always fire");
				Server.NextFrame(() => Console.WriteLine("Sometimes yes sometimes no"));

I can always access to controller, but problem is only with nextframe, because regardless of what i pass here, it often does not fire

I can always access to controller

but you should not. event pointers are released after the callbacks are fired and its not guaranteed that you can still access anything. out of the many reasons this is one of them why we dont have/support async event handlers at the moment.

but this happens even when i use nextframe + console.writeline without the rest of the code, just pure event + nextframe, everything except nextframe will be executed

I quickly looked through the css code, and since Action goes into the nextframe queue that is executed anyway, there should be no problem with console.writeline -- css uses metamod for this, so it may be an bug in metamod or in game

daffyyyy avatar Aug 20 '25 09:08 daffyyyy

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all) instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option) this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

Again, the Player object is not a controller I would also like to add that sometimes there are problems with mysql pooling, and connections used are never released. This has never happened before.

I see that you use a custom player type in the async method, but not in the event handler Image

Same issue with OnGameServerSteamAPIActivated listener, no longer fired on server startup - it behaves as if the server were in hibernation, but it is not. the framework calls the listener when the game calls the given method, not sure if the game has changed something, or if we are refering to the wrong virtual func as there were many sdk changes

				CCSPlayerController? player = @event.Userid;
				if (player == null || !player.IsValid)
					return HookResult.Continue;

				Logger.LogInformation("Always fire");
				Server.NextFrame(() => Console.WriteLine("Sometimes yes sometimes no"));

I can always access to controller, but problem is only with nextframe, because regardless of what i pass here, it often does not fire

I can always access to controller

but you should not. event pointers are released after the callbacks are fired and its not guaranteed that you can still access anything. out of the many reasons this is one of them why we dont have/support async event handlers at the moment.

but this happens even when i use nextframe + console.writeline without the rest of the code, just pure event + nextframe, everything except nextframe will be executed

I quickly looked through the css code, and since Action goes into the nextframe queue that is executed anyway, there should be no problem with console.writeline

"by default" nextframe calls are not processed if the server is hibernating, maybe try the nextworldupdate?

KillStr3aK avatar Aug 20 '25 10:08 KillStr3aK

These methods also do not work when executed from the main thread.

what do you mean? they should work as intended do you have any specific stack or any debug thing?

No errors, just real case example:

LoadPlayer(...)
{
_ = LoadPlayerCacheAsync(player);
}

    public async Task LoadPlayerCacheAsync(Player player)
{
(...)
            if (row != null)
            {
                Logger.LogInformation($"Loaded player data for {player.PlayerName}"); <- this always fire
                //LoadPlayerRowToCache(player, row, false); <--- this always fire

                await Server.NextFrameAsync(() => LoadPlayerRowToCache(player, row, false)); <- this sometimes no
            }
}

and this only happens when there are more players or high uptime. I don't know exactly because it's hard for me to test with real players.

both code you have sent is semantically invalid

So that's why it worked a month ago on all servers and now it doesn't? 0_0 If something has changed, it is worth noting it in the changelog or providing information about it. plugin on which i am currently based worked for a year and then suddenly stopped, so some change must have occurred either in the css or in the game

both code is like a silent bomb, the only reason it worked before is because it didn't explode. more and more people mentioning that there is something wrong with the queued tasks so we might investigate the issue, even though there was no change in the framework in this aspect however as @Mesharsky and I said your codes are semantically wrong. In the event handler you are saving the reference of an event parameter and calling NextFrame and accessing the saved reference which might(/should) get released before NextFrame is called internally (this flow should never work at all) instead, you should save lets say the player slot, and on the next frame just query the player based on the slot and refer to the values using that (you can use whatever, just mentioned slot as an option) this is the same behaviour as using RequestFrameCallback in SourcePawn, just you were working with client ids already back then

Again, the Player object is not a controller I would also like to add that sometimes there are problems with mysql pooling, and connections used are never released. This has never happened before.

I see that you use a custom player type in the async method, but not in the event handler Image

Same issue with OnGameServerSteamAPIActivated listener, no longer fired on server startup - it behaves as if the server were in hibernation, but it is not. the framework calls the listener when the game calls the given method, not sure if the game has changed something, or if we are refering to the wrong virtual func as there were many sdk changes

				CCSPlayerController? player = @event.Userid;
				if (player == null || !player.IsValid)
					return HookResult.Continue;

				Logger.LogInformation("Always fire");
				Server.NextFrame(() => Console.WriteLine("Sometimes yes sometimes no"));

I can always access to controller, but problem is only with nextframe, because regardless of what i pass here, it often does not fire

I can always access to controller

but you should not. event pointers are released after the callbacks are fired and its not guaranteed that you can still access anything. out of the many reasons this is one of them why we dont have/support async event handlers at the moment.

but this happens even when i use nextframe + console.writeline without the rest of the code, just pure event + nextframe, everything except nextframe will be executed I quickly looked through the css code, and since Action goes into the nextframe queue that is executed anyway, there should be no problem with console.writeline

"by default" nextframe calls are not processed if the server is hibernating, maybe try the nextworldupdate?

NextWorldUpdate always work, my servers do not hibernate :( As i in first message, replacing nextframe with nextworldupdate works, but it does not solve the problem, it only creates a workaround.

daffyyyy avatar Aug 20 '25 10:08 daffyyyy

But it could actually be something to do with hibernation (OnGameServerSteamAPIActivated) not working when hibernation is enabled, but now it doesn't work at all - only when the plugin is reloaded.

daffyyyy avatar Aug 20 '25 10:08 daffyyyy

NextFrame works fine. The issue is your code, not the framework. You keep passing around invalid references and then complain when they don’t execute. @KillStr3aK already explained the correct way to do it, but you keep ignoring it. Learn to listen. Might be handy

Mesharsky avatar Aug 20 '25 10:08 Mesharsky

NextFrame works fine. The issue is your code, not the framework. You keep passing around invalid references and then complain when they don’t execute. @KillStr3aK already explained the correct way to do it, but you keep ignoring it. Learn to listen. Might be handy

No, this is not normal behavior only you are retarded who does not understand it

And please don't cry here because you got a timeout and your topic was closed, it just doesn't fool people

daffyyyy avatar Aug 20 '25 10:08 daffyyyy

NextFrame works fine. The issue is your code, not the framework. You keep passing around invalid references and then complain when they don’t execute. @KillStr3aK already explained the correct way to do it, but you keep ignoring it. Learn to listen. Might be handy

No, this is not normal behavior only you are retarded who does not understand it

And please don't cry here because you got a timeout and your topic was closed, it just doesn't fool people

Insults don’t change facts. NextFrame works as intended, your misuse of it is the problem. It was already explained why your approach is invalid and how to fix it. If you are not willing to listen, there is nothing more to add.

Mesharsky avatar Aug 20 '25 10:08 Mesharsky

I use several public plugins that use NextFrame, all of which stop working after anywhere between 6-24h with 25+ players on constantly, its very inconsistent and will work for a bit after map change, then stop and break completely. And then on server restart it works until the time frame mentioned above. An example of a plugin that breaks would be SharpTimer, which uses a lot of NextFrames, if this is an issue with the way things are created, then a notice should probably be put out in regards to the issue, but its very weird how it never had an issue pre the 18th update, and works for a while before breaking only dependent on the player count

If someone could tell me if for instance SharpTimer above is using NextFrame in a way thats prone to breaking, I'd appreciate so I can forward the message, but its not just that plugin, search query showing their usage: here

Damien111 avatar Aug 20 '25 11:08 Damien111

I use several public plugins that use NextFrame, all of which stop working after anywhere between 6-24h with 25+ players on constantly, its very inconsistent and will work for a bit after map change, then stop and break completely. And then on server restart it works until the time frame mentioned above. An example of a plugin that breaks would be SharpTimer, which uses a lot of NextFrames, if this is an issue with the way things are created, then a notice should probably be put out in regards to the issue, but its very weird how it never had an issue pre the 18th update, and works for a while before breaking only dependent on the player count

If someone could tell me if for instance SharpTimer above is using NextFrame in a way thats prone to breaking, I'd appreciate so I can forward the message, but its not just that plugin, search query showing their usage: here

"fire and forget" calls can swallow exceptions, you can try to set an TaskScheduler.UnobservedTaskException handler

KillStr3aK avatar Aug 20 '25 11:08 KillStr3aK

This looks odly similar to an issue I've reported back in feb in the discord server, so it's unlikely due to illegal usage of the NextFrame blocks as it should still do something even if not correct given the context.

aquevadis avatar Aug 20 '25 11:08 aquevadis

Server.NextWorldUpdate seems to also be broken when sv_hibernate_when_empty is enabled.

tslashd avatar Aug 21 '25 07:08 tslashd

100% or partially related to threadpool? I used Semaphore to limit concurrent tasks + increased maximum number of processes in system, and problem does not occur or occurs very rarely.

daffyyyy avatar Aug 23 '25 08:08 daffyyyy

Server.NextWorldUpdate seems to also be broken when sv_hibernate_when_empty is enabled.

hibernate should not affect NextWorldUpdate, this whole case seems a bit odd

KillStr3aK avatar Aug 23 '25 14:08 KillStr3aK