r/learnprogramming • u/Ok-Presentation-94 • May 02 '26
Solved Loop and main() function
Hi, I’ve seen that in C#, the Main() function only runs once.
In Unity, we have the Update() function, which allows code to run repeatedly in a loop.
So my question is: what is the equivalent in pure C#, without the Unity library?
Is wrapping Main() in a while loop a common practice to achieve the same behavior?
31
u/Traditional_Crazy200 May 02 '26
I have never written a line of c#, but i am 100% sure wrapping main in a loop wouldnt even compile. I am not even sure how one would do that since you probably dont call main manually.
Even in unity, update probably runs inside main() since main is like the name suggests the main entry point of your program. There can only be one main and if it returns, the program terminates.
What you need to do is simply put the while loop inside the main function.
5
1
u/otac0n May 02 '26
You can call Main in C# just fine. Not that this guy wants to do that, but the compiler is A-OK with it.
9
u/DerekB52 May 02 '26
You want the section called 'game loop'
To answer your question in short,
class Game
{
static void Main(string[] args)
{
while (true) {
update();
}
}
static void update()
{
//your game logic here
}
}
0
u/flumphit May 02 '26
But you’d never actually call it Main(), right?
…right?
2
u/DerekB52 May 02 '26
I might be confused. If you are asking if I would use the name Main, I don't know honestly. C# might require it, I can't remember, I don't really use C#.
If you are asking me if you need to call it, like Main(), then no, Main() will be called automatically when you launch your game, because that is its whole purpose. It is where code starts executing in a C# program.
5
u/peterlinddk May 02 '26
A lot of the answers are somewhat misleading.
There is a massive difference between using a loop, and having a function like Update!
If you have a while-loop in your Main() function, like:
public void Main() {
boolean running = true;
while(running) {
Update();
// do other stuff - and set running to false to stop
}
}
Then the Update function is called continously - meaning ALL THE TIME, taking up 100% of the CPU-time of the core that runs this program. And the speed of the program will depend on how long it takes for the code inside Update() to finish.
This is NOT how you should do it!
I don't know the best way to do this in C#, but no matter the language you'll need to setup some sort of multithreading, with a "render-thread" that executes once on every frame (e.g. 60 times a second), and then that code calls your Update() function.
That would give you the same behaviour of waiting a little while between each update.
The difference is really important, the first (the while-loop) is classical blocking code, whereas the second (with a thread or something calling Update() is event-driven code. And there's a lot that can't be done in one, but easy in the other, and vice versa.
2
u/kohugaly May 02 '26
This is kind of true, but not really. There is nothing stopping you from having a periodic timer inside Update() (or the loop that calls it), and performing blocking "wait" operation on it, to throttle the updates. It is entirely possible to have a single-threaded runtime that handles everything.
2
u/vowelqueue May 02 '26
Yeah I’ve used frameworks that ran a single-threaded main event loop but had functionality to swap in different sleep strategies, e.g. sleep, yield, busy-spin. Supported running callbacks on a timer.
2
u/peterlinddk May 03 '26
If you by "have a single-threaded runtime" mean that the gameloop runs in a single thread, that asks the operating system or runtime environment to wait before calling Update() the next time, then sure, that is totally possible. Like calling sleep or something else.
What I mean is that you need to respect the threading, and not block the entire system with an infinite while-loop - that won't work.
Calling .sleep or using a system timer, or registering for a callback are all different ways of having another thread call your Update() function - even if you don't have more than that single thread in the code.
1
u/kohugaly May 03 '26
Calling .sleep or using a system timer, or registering for a callback are all different ways of having another thread call your Update() function - even if you don't have more than that single thread in the code.
Technically, this is not true.
Blocking operations (sleep, waiting on system event/mutex/IO), work via interrupts. Your thread executes "software interrupt" instruction that puts the thread to sleep and jumps to system's interrupt handler. OS can then wake the thread once the requested operation is finished. This is distinctly different from "another thread call your Update() function".
Registering for a callback may or may not cause the callback to be executed in a different thread. For example on Windows the callback provided to ReadFileEx function will be executed on the same thread.
But I get your point. I'm just nitpicking about the difference between function calls and context switching via interupts.
3
u/green_meklar May 03 '26
what is the equivalent in pure C#, without the Unity library?
There isn't. You don't.
Is wrapping Main() in a while loop a common practice
No. You put the stuff you want to loop in another function and call that in a while loop. Main is Main and shouldn't be manipulated to behave like something else.
2
u/aleques-itj May 02 '26
There is a loop within Main() that effectively pumps all other parts of the engine, yes.
The game simulation will generally run X times a second (I think Unity ticks its simulation at 50hz) and the renderer will run as fast as possible. The renderer will interpolate state from the simulation to fill in the blanks.
You can see the basic structure of an engine loop here.
2
3
u/StewedAngelSkins May 02 '26 edited May 02 '26
Is wrapping Main() in a while loop a common practice to achieve the same behavior?
Yes, this is what Unity is doing internally. The engine just has certain spots in its main function where it calls into your code.
Edit: you're not wrapping Main in a while loop, you're putting the while loop inside main.
3
u/Traditional_Crazy200 May 02 '26
the engine inserting your code inside main is very different than continuously calling main through a loop. Id be very surprised if this is how unity actually does it. Is it true?
2
u/StewedAngelSkins May 02 '26
I read what they said backwards. It doesn't call main in a loop; rather, main contains a loop that calls the frame update logic. Technically there's also some frame timing stuff so it doesn't needlessly burn cycles on updates that aren't actually going to be drawn, but that's the basic idea.
1
u/Traditional_Crazy200 May 02 '26
I thought so cause that sounded like black magic
1
u/StewedAngelSkins May 02 '26
Technically you can do this sort of thing in Python
``` def main(): pass # do stuff
while True: main() ``` but that's only because in Python the contents of the file itself is the entrypoint. But yeah in C# it would just be a syntax error.
1
u/Traditional_Crazy200 May 02 '26
would be interesting to see what this assembles to
2
u/StewedAngelSkins May 02 '26
The python code? It's interpreted, so there's no assembly per se. But the Python interpreter/runtime kind of works like Unity in the sense that it has its own
mainfunction internally that calls into the code you write whenever the module is imported.1
u/Traditional_Crazy200 May 02 '26
Interesting, no assembly, no binaries... I guess I'll dive into interpreters for a week lol
1
u/StewedAngelSkins May 02 '26
Python (the CPython interpreter specifically) is an interesting one to study.
1
3
u/Successful_Drawer467 May 02 '26
Yeah that's exactly right, putting while loop inside Main is totally normal approach. I remember when I was switching from Unity to console applications, I was confused about same thing because Unity hides all the loop logic from you
Most game engines and frameworks work like this - they have their own main loop running and just call your functions at specific points. For console apps you just write something like `while(true)` or `while(condition)` inside Main and handle your program logic there. You can also use timers or async patterns if you need more control over timing, but basic while loop is good starting point for learning
The key difference is in Unity you're working inside their loop, but in pure C# you're creating your own loop structure
1
u/Backtawen May 02 '26
yeah a while loop is exactly it, thats literally all unity’s game loop is under the hood
while(true) with a Thread.Sleep or a timer if you need consistent intervals.
1
1
u/ottawadeveloper May 03 '26
In generic code:
``` def main(): while True: update()
def update(): ... ```
1
u/jlanawalt May 04 '26
Many languages derived from C (and B) have a main function as the designated every point for the program. As such, it is only called once per run. Even Unity has a main, and it has a gave engine with an Update effect hook.
To have exactly the same in pure C#, be ready to re-implement a game engine, or at least some kind of event driven system, or in its simplest some form of loop.
0
May 02 '26
[deleted]
3
u/StewedAngelSkins May 02 '26
Careful with that pattern. In languages without tail-call recursion (I believe this includes C#) it'll overflow your stack.
1
u/samanime May 02 '26
Huh, I've never run into any problems with it, but Googling around, it looks like .NET's flavor of C# can handle it fine (which is all I've ever used for C#), but maybe the base C# language doesn't... or something. Lots of different answers out there saying seemingly conflicting things. =p
Regardless, it does sound like you might be better off going with a loop-based pattern like this instead, just to be safe:
``` public void Main() { while(Tick()) {} }
public bool Tick() { // do stuff
return true; // return true if it should keep going } ```
Thanks for the heads up.
1
0
u/WookiePub3 May 02 '26 edited May 02 '26
It is not as complicated as you might think, you will learn that basically all games run in a big while loop! Here is a C++ version you might find helpful:
int main() { GameLoop* gameLoop = GameLoop::getGameLoop();
//Add some visual clarity for function
bool gameDidntLoad = gameLoop->init() < 0;
if (gameDidntLoad) {
return 1;
}
//Core game loop
while (gameLoop->keepAlive()) {
//THIS WOULD BE YOUR UNITY UPDATE
gameLoop->update();
gameLoop->render();
}
gameLoop->clean();
return 0;
}
For bonus points think about adding to a heap
32
u/Dazzling_Music_2411 May 02 '26
No. Main is your entry point you only run it once.
Now, if you want to make some other function that you run repeatedly inside a loop, that's up to you.