Time Throwing (Threads)

1

What you need to answer the question is in comments in the code:

using System;
using System.Threading.Tasks;

class Program
{

    static void Main(string[] args)
    {
        player1.Start();
        t.Start();

        while (t.IsAlive); //A intenção seria depois que o Thread t acabar se a Thread player1 
                            //ainda estiver ativa o jogador perde a rodada.
                            //gostaria também de que se a Thread player1 já acabou
                            //a Thread t pode se encerrar.
        if (player1.IsAlive) player1.Abort(); Console.Write("\nSeu Tempo Acabou");
    }

    static void player()
    {
        Console.Write("Player1 Escreva Algo (Nao Deixe Passar 10 Segundos): ");
        str += Console.ReadLine() + " ";
        Console.Write(" {0}", str);
    }

    static void tempo()
    {
        System.Threading.Thread.Sleep(10000); //10 sec = 10.000 milisec
    }

    static String str = "";
    static System.Threading.Thread player1 = new System.Threading.Thread(player);
    static System.Threading.Thread t = new System.Threading.Thread(tempo);

}

Ex: In chess games you have a time available to move your piece, if you do not move within eg 30 seconds you lose your move and it is the turn of the next player (Ai would show the message), now if you move your piece ahead of time, you just pass the turn to another player without losing anything. The idea is +/- this.

    
asked by anonymous 27.12.2014 / 21:17

3 answers

1

I came back in the code and realized that it was only to change the function void player() that worked exactly as I wanted, so it looked like this:

static void player()
{
    Console.Write("Player1 Escreva Algo (Nao Deixe Passar 10 Segundos): ");
    str += Console.ReadLine();
    Console.Write("\"{0}\"", str);
    t.Abort();
}

And I've also changed that:

while (t.IsAlive);
if (player1.IsAlive) { player1.Abort(); Console.Write("\nSeu Tempo Acabou"); }

For this:

while (t.IsAlive);
System.Threading.Thread.Sleep(1);
if (player1.IsAlive) { player1.Abort(); Console.Write("\nSeu Tempo Acabou"); }

When t.Abort() occurs in Thread player1 the while(t.IsAlive) of Thread of main is terminated.

Because when it exits from while (t.IsAlive); it goes to: if (player1.IsAlive) I do not know why player1 continued Alive even after passing the line t.Abort(); ai when it arrives in if (player1.IsAlive) it was validated as true, and player1 had already finished. I solved it by placing 1 millisecond between the while and the if.

But I also really liked the other answers, I put mine here just to show you another way out.

    
30.12.2014 / 19:05
3

Using the Task it's easy to do what you want:

class Program
{
    static void Main(string[] args)
    {
        String str = null;

        //Objectos que permitem cancelar as Tasks
        var tokenSourceTempo = new CancellationTokenSource();
        var ctTempo = tokenSourceTempo.Token;
        var tokenSourcePlayer = new CancellationTokenSource();
        var ctPlayer = tokenSourcePlayer.Token;

        //Cria a task que espera 10 segundos até 
        Task.Factory.StartNew(
            () =>
            {
                Thread.Sleep(10000);

                if (ctTempo.IsCancellationRequested != true)
                {
                    tokenSourcePlayer.Cancel(); //Cancela a task player
                    Console.Write("\nSeu Tempo Acabou\n");
                }
            }, ctTempo);

        //Cria a task player
        var taskPlayer = Task.Factory.StartNew(
            () =>
            {
                var key = new ConsoleKeyInfo();

                Console.Write("Player1 Escreva Algo (Nao Deixe Passar 10 Segundos): ");

                while (key.Key != ConsoleKey.Enter)//Aceita teclas até a tecla enter ser usada
                {

                    key = Console.ReadKey();
                    ctPlayer.ThrowIfCancellationRequested();//Se a task player foi cancelada aborta
                    tokenSourceTempo.Cancel();//O player teclou algo, cancela task tempo
                    str += key.KeyChar;//Constroi string
                }

            }, ctPlayer);

        try
        {
            taskPlayer.Wait();// Espera enquanto o player tecla algo
            Console.Write("\nVocê escreveu: {0}\n", str);
            Console.ReadKey();
        }
        catch (AggregateException e)//Quando a task player é cancelada é lançada uma Exception
        {
            if (taskPlayer.IsCanceled)
            {

            }
        }
    }
}

You will now have to adjust to your needs. Use ctrl + F5 to test if you are using Visual Studio.

    
27.12.2014 / 22:04
1

Well, I created some classes to make it easier to understand. The comments will help you understand the flow.

using System;
using System.Threading;

namespace Pt.Stackoverflow
{
    class Program
    {
        static void Main()
        {
            // nova partida
            var match = new Match(new Player("Player 1"), 60);

            //Ação customizada que será executada quando o usuário digitar algum texto
            match.OnPlayerInput += input =>
            {
                Console.WriteLine("Usuário escreveu: \"{0}\"", input);
                match.Finish();
            };

            //Ação customizada que será executada quando a partida for encerrada, 
            //ou seja, por tempo ou pela chamada do método Finish() e não pelo fechamento da Aplicação.
            match.OnMatchEnd += () => Console.WriteLine("Tchau!");

            match.Start();
        }
    }

    class Match
    {
        /// <summary>
        /// Tempo em segundos.
        /// </summary>
        public uint Time { get; private set; }
        /// <summary>
        /// Player atual
        /// </summary>
        public Player CurrentPlayer { get; private set; }
        /// <summary>
        /// Chamado quando o usuário escreve algo.
        /// </summary>
        public event Action<string> OnPlayerInput;
        /// <summary>
        /// Chamado quando a partida termina.
        /// </summary>
        public event Action OnMatchEnd;

        private AutoResetEvent _autoEvent;
        private TimerCallback _tick;
        private Timer _timer;
        private readonly Thread _matchThread;

        private const int AGORA = 0, SEGUNDO = 1000, MINUTO = 60000;

        /// <summary>
        /// Criar uma nova partida
        /// </summary>
        /// <param name="player">Jogador atual</param>
        /// <param name="time">Tempo da partida</param>
        public Match(Player player, uint time) {
            CurrentPlayer = player; 
            Time = time;

            _matchThread = new Thread(() =>
            {
                Console.WriteLine(">> {0} Escreva Algo (Nao Deixe Passar 10 Segundos): ", player.Name);
                On_PlayerInput(Console.ReadLine());
            });
        }

        /// <summary>
        /// Inicia a partida
        /// </summary>
        public void Start()
        {
            if (Time == 0)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Esta partida já foi encerrada.");
                Console.ForegroundColor = ConsoleColor.White;
                return;
            }

            Console.Clear();
            Console.ForegroundColor = ConsoleColor.White;

            // Usado para fazer com que o timer seja repetido.
            _autoEvent = new AutoResetEvent(false);
            // Callback do Timer
            _tick = Tick;
            // Timer disparado imediatamente e chamado a cada segundo
            _timer = new Timer(_tick, _autoEvent, AGORA, SEGUNDO);

            //Capturar do input do usuário
            _matchThread.Start();

            Console.WriteLine(">> Partida Iniciada.");
        }

        /// <summary>
        /// Termina a partida
        /// </summary>
        public void Finish()
        {
            _timer.Dispose();
            _autoEvent.Dispose();
            Time = 0;

            if (OnMatchEnd != null) OnMatchEnd();
            Console.WriteLine(">> Partida concluída.");
            Console.Read();
            _matchThread.Abort();
        }

        /// <summary>
        /// Chamado a cada segundo passado
        /// </summary>
        /// <param name="stateInfo"></param>
        private void Tick(Object stateInfo)
        {
            //Console.WriteLine(">> Tempo atual da partida: {0}s", Time);
            if (--Time == 0) Finish();
        }

        /// <summary>
        /// Chamado quando o usuário digitar um texto (após apertar Enter)
        /// </summary>
        /// <param name="input">Texto digitado</param>
        private void On_PlayerInput(string input)
        {
            //Console.WriteLine(">> Usuário escreveu: {0}", (CurrentPlayer.Input = input));
            if (OnPlayerInput != null) OnPlayerInput(input);
        }
    }

    class Player
    {
        /// <summary>
        /// Nome do jogador
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// Texto digitado pelo jogador
        /// </summary>
        public string Input { get; set; }

        public Player(string name) { Name = name; }
    }
}
    
29.12.2014 / 03:04