c#中的任务重复调用一个任务

本文关键字:任务 一个 调用 | 更新日期: 2023-09-27 18:13:39

我想做的是在主机应用程序中编写俄罗斯方块游戏。这是我的问题:我有两个叫做ListenToKeyEvents和DropTetramino的函数,我如何调用这两个任务来执行块的下落,如果在调用DropTetramino之前有用户的输入对输入作出反应?

以下是我到目前为止所做的尝试:

Thread.CurrentThread.Name = "Main";
        Task taskA = new Task(() => ListenToKeyEvents());
        Task taskB = new Task(() => DropTetramino());
        // Start the task.
        taskA.Start();
        Thread.Sleep(1000);
        taskB.Start();

        // Output a message from the calling thread.
        Console.WriteLine("Hello from thread '{0}'.",
                          Thread.CurrentThread.Name);
        taskA.Wait();
        taskB.Wait();

private static void ListenToKeyEvents()
    {
        ConsoleKeyInfo x = new ConsoleKeyInfo();
        while (!Console.KeyAvailable && x.Key != ConsoleKey.Escape)
        {
            x = Console.ReadKey(true);
            if (x.Key == ConsoleKey.UpArrow)
            {
                Blockrotieren();
            }
            if (x.Key == ConsoleKey.DownArrow)
            {
            }
            if (x.Key == ConsoleKey.LeftArrow)
            {
            }
            if (x.Key == ConsoleKey.RightArrow)
            {
            }
            if (x.Key == ConsoleKey.Spacebar)
            {
            }
        }
    }

private static void DropTetramino()
    {
        List<char> belegt = new List<char> ();
        for (int i = 0; i < 21; i++)
        {
            char[] z = feld[i].ToCharArray();
            for(int j = 0; j < 12; j++)
            {
            belegt.Add(z[j]);
            }
        }
        int[] x = new int[4];
        int[] y = new int[4];
        int[] x1 = new int[173];
        int[] y1 = new int[173];
        int countrows = 0;
        int sum = 0;
        int s = 0;
        int s1 = 0;
        foreach (char i in belegt)
        {
            if (s >= 4)
            {
                //break;
                //alle übrigen nicht fallenden Blöcke
                if ((sum % 12) == 0 && sum != 0)
                countrows++;
            if (i == 'ö')
            {
                x1[s1] = sum % 12;
                y1[s1] = countrows;
                s1++;
                s++;
            }
            if (i == '*' && ((sum % 12) != 0))
            {
                x1[s1] = sum % 12;
                y1[s1] = countrows;
                s1++;
                s++;
            }
            sum += 1;
            }
            if ((sum % 12) == 0 && sum != 0)
                countrows++;
            if (i == 'ö')
            {
                x[s] = sum % 12;
                y[s] = countrows;
                Console.WriteLine("x {0} y {1}", x[s], y[s]);
                s++;
            }
            sum += 1;
        }
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                if ((i - j) > -1 && (i - j) < 4)
                {
                    if (y[i] > y[i - j] && x[i] == x[i - j])
                    {
                        x[i - j] = -1;
                        y[i - j] = -1;
                    }
                    if (y[i] < y[i - j] && x[i] == x[i - j])
                    {
                        x[i] = -1;
                        y[i] = -1;
                    }
                }
            }
        }
        for (int i = 0; i < 4; i++)
        {
            Console.WriteLine("x rel {0} y rel {1}", x[i], y[i]);
        }
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < x1.Length; j++)
            {
                if ((y[i] != -1 && (y[i] + 1) == y1[j]) && x[i] == x1[j])
                {
                    return;
                }
            }
        }
        Console.Clear();
        Blockrotieren(xyPos);
    }

也许这不是最好的代码,但这两个函数做他们的工作,但只有一次,我不知道如何反复调用它们

c#中的任务重复调用一个任务

我认为你可以通过理解线程信令来解决你的问题。下面是一个定制的控制台应用程序示例。这不是一个很好的现实场景,但是线程信号的使用是存在的。

using System;
using System.Threading;
class Program
{
    static void Main()
    {
        bool isCompleted = false;
        int diceRollResult = 0;
        // AutoResetEvent is one type of the WaitHandle that you can use for signaling purpose.
        AutoResetEvent waitHandle = new AutoResetEvent(false);
        Thread thread = new Thread(delegate() {
            Random random = new Random();
            int numberOfTimesToLoop = random.Next(1, 10);
            for (int i = 0; i < numberOfTimesToLoop - 1; i++) {
                diceRollResult = random.Next(1, 6);
                // Signal the waiting thread so that it knows the result is ready.
                waitHandle.Set();
                // Sleep so that the waiting thread have enough time to get the result properly - no race condition.
                Thread.Sleep(1000);
            }
            diceRollResult = random.Next(1, 6);
            isCompleted = true;
            // Signal the waiting thread so that it knows the result is ready.
            waitHandle.Set();
        });
        thread.Start();
        while (!isCompleted) {
            // Wait for signal from the dice rolling thread.
            waitHandle.WaitOne();
            Console.WriteLine("Dice roll result: {0}", diceRollResult);
        }
        Console.Write("Dice roll completed. Press any key to quit...");
        Console.ReadKey(true);
    }
}

你可以做的一件事是你可以从你的任务中同步调用你的ListenToKeyEvents()函数,让它工作一段时间,不管执行结果如何都调用DropTetramino()。但要做到这一点,你需要限制玩家的反应时间:

private static void ListenToKeyEvents()
{
    int timeToReact = 1000; // your time for user to react in ms
    ConsoleKeyInfo x = new ConsoleKeyInfo();
    Stopwatch s = new Stopwatch();
    s.Start();        
    while (s.ElapsedMilliseconds < timeToReact && !Console.KeyAvailable && x.Key != ConsoleKey.Escape)
    {
       // ..... your code 
    }
    s.Stop();
}
Task taskA = new Task(() => 
{
   // Whether or not user pressed arrows 
   // ListenToKeyEvents finishes executing
   // DropTetraMino is invoked and it is repeated 
   while(gameIsOn)
   {
       ListenToKeyEvents();
       DropTetramino();
   }
});
// Start the task.
taskA.Start();    
taskA.Wait();