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

时间:2015-09-20 09:15:20

标签: c# task

我想要做的是在控制台应用程序中编写俄罗斯方块游戏。 这是我的问题:我有两个叫做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);
    }

也许这不是最好的代码,但这两个功能可以完成他们的工作,但只有一次,我不知道如何反复调用它们。

2 个答案:

答案 0 :(得分:0)

我认为您可以通过了解Thread Signaling来解决您的问题。 这是一个定制的控制台应用程序示例。实际上并不是一个好的现实场景,但线程信令的使用就在那里。

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);
    }
}

答案 1 :(得分:0)

您可以做的一件事是您可以从任务中同步调用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();