rathi bond rathi bond - 1 year ago 208
C# Question

How many Tasks are too many

I am working on a spaceship shooter style game. In the game there are slow moving missiles that I run on different tasks.

Task t4 = new Task(() => fireShipCannons());

They don't do much; just move a small bitmap across the screen. Usually it is a for loop with 30 iterations. The problem is that the timing is off and some tasked seem to take priority over others. I also many be important to note that to control the speed of the missiles I am using Thread.Sleep(100). Because of this slowing down, the method will run for a few seconds.

I am using c#, .net, Windows Form Application

I have spent hours thinking about how to reword this, and I think it is worded correctly. The problem I was having was broad; so yes, the question may be a bit broad. I got a great answer! Does that not indicate that the question was asked correctly?

Answer Source

Since you are already using Tasks (good), you can simply make them async Tasks and use await Task.Delay(time).

    async Task fireShipCannons(CancellationToken ct)
        for (int i = 0; i < distance; i++) {
           await Task.Delay(100, ct);

This way you will not tie up 1 thread for every bullet. Most likely your tasks are currently slow because you reach the limit of your threadpool, so this should be a lot faster. But additionally, you should also check if Task.Delay has taken more than the 100 ms you suggested. If it did, draw the bullet 2 spots further instead of 1, and reschedule accordingly.

    async Task fireShipCannons(CancellationToken ct)
        var start = DateTime.Now;
        while (bullet.isOnscreen) {
           var sleep = (start.Add(TimeSpan.FromMilliseconds(100.0)) - DateTime.Now);
           if (sleep.Milliseconds > 0) {
               Task.Delay(sleep, ct);
           iter = (int)((DateTime.Now - start).TotalMilliseconds / 100 + 0.5);
           bullet.moveSteps(iter); // move it iter steps.
           var start = start.AddMilliseconds(100 * it);

Lastly, it might be a good idea to not hammer your draw function with new calls for every bullet, but instead combine all bullets/changes into a single render function that calculate all changes and sends them off in one go. But that depend on how your draw function itself is implemented.