private void BtnProcessar_Click_Bloqueando(object sender, RoutedEventArgs e)
        {
            BtnProcessar.IsEnabled  = false;
            BtnProcessar1.IsEnabled = false;
            BtnProcessar2.IsEnabled = false;
            BtnProcessar3.IsEnabled = false;
            var textoInicial = BtnProcessar2.Content;

            BtnProcessar2.Content = "Processando...";

            var contas = r_Repositorio.GetContaClientes();

            var resultado = new List <string>();

            LimparView();

            var inicio = DateTime.Now;

            foreach (var conta in contas)
            {
                var resultadoConta = r_Servico.ConsolidarMovimentacao(conta);
                resultado.Add(resultadoConta);
            }

            var fim = DateTime.Now;

            AtualizarView(resultado, fim - inicio);

            BtnProcessar.IsEnabled  = true;
            BtnProcessar1.IsEnabled = true;
            BtnProcessar2.IsEnabled = true;
            BtnProcessar3.IsEnabled = true;
            BtnProcessar2.Content   = textoInicial;
        }
コード例 #2
0
        private void BtnProcessar_Click(object sender, RoutedEventArgs e)
        {
            var taskSchedulerUI = TaskScheduler.FromCurrentSynchronizationContext(); //Pegar a task scheduler da UI está em execução

            BtnProcessar.IsEnabled = false;

            var contas = r_Repositorio.GetContaClientes();

            var resultado = new List <string>();

            AtualizarView(new List <string>(), TimeSpan.Zero);

            var inicio = DateTime.Now;

            var contaTarefas = contas.Select(conta =>
            {
                return(Task.Factory.StartNew(() =>
                {
                    var resultadoConta = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoConta);
                }));
            }).ToArray();//O ToArray() serve para a execução do linq

            //Task.WaitAll(contaTarefas);
            Task.WhenAll(contaTarefas).ContinueWith(task =>
            {
                var fim = DateTime.Now;
                AtualizarView(resultado, fim - inicio);
            });
        }
コード例 #3
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas,
                                                       IProgress <string> progresso,
                                                       CancellationToken ct)
        {
            var tasks = contas.Select(conta =>
            {
                return(Task.Factory.StartNew(() =>
                {
                    if (ct.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(ct);
                    }

                    var consolidacao = r_Servico.ConsolidarMovimentacao(conta);
                    progresso.Report(consolidacao);

                    if (ct.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(ct);
                    }

                    return consolidacao;
                }, ct));
            });

            return(await Task.WhenAll(tasks));
        }
コード例 #4
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> reportadorDeProgresso, CancellationToken ct)
        {
            /*
             * Parece que algo está estranho, pois estamos retornando uma lista vazia. Até o método ConsolidarContas retornar,
             * nenhuma tarefa terá o processamento terminado. Na realidade, o que vamos retornar neste método não será uma lista de string,
             * e sim uma tarefa que retorna uma lista de string. Ainda não vimos uma tarefa com retorno, mas isto é possível, sendo do mesmo
             * tipo, porém genérico. Vamos utilizá-la como uma lista. Teremos uma task e, entre os sinais de maior e menor, indicamos o
             * retorno da tarefa correspondente, no caso, uma lista de string.
             */

            var tasks = contas.Select(conta =>
                                      Task.Factory.StartNew(() => {
                ct.ThrowIfCancellationRequested();

                var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta, ct);
                reportadorDeProgresso.Report(resultadoConsolidacao);

                ct.ThrowIfCancellationRequested();

                return(resultadoConsolidacao);
            })
                                      );

            /*
             *  temos várias tarefas (tasks), todas retornando o mesmo tipo, e com o resultado, teremos uma tarefa que retorna
             *  um array deste tipo. Como podemos utilizar isto? Guardaremos o WhenAll de todas estas tarefas em uma variável.
             *  Aqui, não queremos uma task, e sim o resultado, portanto podemos usar apenas o await, tendo como resultado um
             *  array de string
             */
            return(await Task.WhenAll(tasks));
        }
コード例 #5
0
        // Retornara uma Tarefa que irá retornar as contas consolidadas
        private Task <List <string> > ConsolidarContas(IEnumerable <ContaCliente> contas)
        {
            var resultado = new List <string>();

            // Realizando o mapeamento para que cada conta seja consolidada por uma task, a task será armazenada no array
            var tasks = contas.Select(conta =>
            {
                // Para cada conta uma Task será criada e iniciada
                return(Task.Factory.StartNew(() =>
                {
                    // Realizará a consolidação dessa conta e adicionara o resultado na lista de contas
                    var resultadoConta = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoConta);
                }));
            });

            // Quando todas as tarefas do array de tasks anterior forem terminadas
            // uma nova task sera executada, que apenas irá retornar o resultado da consolidação
            // de todas as contas

            // Task.WhenAll() => retornará uma outra tarefa que só tem a função de esperar as tarefas que são passadas por parametro terminarem (array)
            return(Task.WhenAll(tasks).ContinueWith(task =>
            {
                // O retorno da tarefa será o resultado da consolidação
                return resultado;
            }));

            // ContinueWith => Irá encadear outra tarefa após a execução da anterior, ou seja no exemplo acima
            // só será executada quando a tarefa que espera as tasks do array forem terminadas

            // task => task que originou a tarefa atual
        }
コード例 #6
0
        private async Task <string[]> ConsolidaContas(IEnumerable <ContaCliente> contas)
        {
            var tarefas = contas.Select(conta =>
                                        Task.Factory.StartNew(() => r_Servico.ConsolidarMovimentacao(conta))
                                        );

            return(await Task.WhenAll(tarefas));
        }
コード例 #7
0
 private void ConsolidarMovimentacao(IEnumerable <ContaCliente> contas)
 {
     foreach (var conta in contas)
     {
         var resultadoProcessamento = r_Servico.ConsolidarMovimentacao(conta);
         resultado.Add(resultadoProcessamento);
     }
 }
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas)
        {
            var _tasks = contas.Select(conta =>
                                       Task.Factory.StartNew(() => r_Servico.ConsolidarMovimentacao(conta))
                                       );

            var resultado = await Task.WhenAll(_tasks);

            return(resultado);

            #region Como realizar sem o Async Await
            //var _tasks = contas.Select(conta =>
            //{
            //    return Task.Factory.StartNew(() =>
            //    {
            //        var contaResultado = r_Servico.ConsolidarMovimentacao(conta);
            //        resultado.Add(contaResultado);
            //    });
            //}).ToArray();

            //return Task.WhenAll(_tasks)
            //    .ContinueWith(task =>
            //    {
            //        return resultado;
            //    });
            #endregion
        }
コード例 #9
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> reportadorDeProgresso, CancellationToken ct)
        {
            var tasks = contas.Select(conta =>
            {
                return(Task.Factory.StartNew(() =>
                {
                    // Verificando se a tarefa foi cancelada em tempo de execução
                    if (ct.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(ct);
                    }

                    var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta, ct);

                    // Efetuando a atualização da barra de progresso
                    reportadorDeProgresso.Report(resultadoConsolidacao);

                    // Outra meneira de verificar se a tarefa foi cancelada
                    ct.ThrowIfCancellationRequested();

                    return resultadoConsolidacao;
                }, ct)); // Passando o CancellationToken como parametro, para ele não iniciar tarefas caso o usuario tenho cancelado a requisição
            });

            var resultado = await Task.WhenAll(tasks);

            return(resultado);
        }
コード例 #10
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> progress)
        {
            var tasks = contas.Select(conta => Task.Factory.StartNew(() =>
            {
                var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta);

                progress.Report(resultadoConsolidacao);

                return(resultadoConsolidacao);
            }));

            return(await Task.WhenAll(tasks));
        }
コード例 #11
0
        // A tarefa de consolidar contas tambem é executada de forma assíncrona e retorna uma tarefa que retorna um array de strings
        public async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas)
        {
            var resultado = new List <string>();

            // Para cada conta da lista, eu crio uma task e já a inicio, cada task irá consolidar uma conta dessa lista e retornar uma String (conta consolidada)
            // a task criada será armazenada em um array de tasks
            var tasks = contas.Select(conta =>
                                      Task.Factory.StartNew(() => r_Servico.ConsolidarMovimentacao(conta)));

            // com await => segue o fluxo desse método até que todas as tasks do array terminem o seu processo
            // (Como é um array de tarefas, o resultado final será tmb um array de resultados (Strings que representa uma conta consolidada)
            return(await Task.WhenAll(tasks)); // Retorna uma tarefa que devolve um array de contas consolidadas
        }
コード例 #12
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> progress, CancellationToken ct)
        {
            var tarefas = contas.Select(conta => Task.Factory.StartNew(() =>
            {
                ct.ThrowIfCancellationRequested();
                var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta, ct);
                ct.ThrowIfCancellationRequested();

                progress.Report(resultadoConsolidacao);
                return(resultadoConsolidacao);
            }, ct));

            return(await Task.WhenAll(tarefas));
        }
コード例 #13
0
        private async Task <int> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> reportProgressUser, CancellationToken ct)
        {
            var totalProcessado = 0;
            var tasks           = contas.Select(conta =>
                                                Task.Factory.StartNew(() =>
            {
                ct.ThrowIfCancellationRequested();
                var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta, ct);
                ct.ThrowIfCancellationRequested();
                reportProgressUser.Report(resultadoConsolidacao);
                totalProcessado++;
            }, ct));

            await Task.WhenAll(tasks);

            return(totalProcessado);
        }
コード例 #14
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> reportadorDeProgresso, CancellationToken ct)
        {
            var tasks = contas.Select(conta =>
                                      Task.Factory.StartNew(() => /*inicia novas tarefas para cada conta. A factory cogerencia as tarefas entre os nucleos do processador*/
            {
                ct.ThrowIfCancellationRequested();

                var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta, ct);

                reportadorDeProgresso.Report(resultadoConsolidacao);

                ct.ThrowIfCancellationRequested();
                return(resultadoConsolidacao);
            }, ct)
                                      );

            return(await Task.WhenAll(tasks)); /*Só retorna quando todos os processos terminarem*/
        }
コード例 #15
0
        private Task <List <string> > ConsolidarContas(IEnumerable <ContaCliente> contas)
        {
            /*
             * Parece que algo está estranho, pois estamos retornando uma lista vazia. Até o método ConsolidarContas retornar,
             * nenhuma tarefa terá o processamento terminado. Na realidade, o que vamos retornar neste método não será uma lista de string,
             * e sim uma tarefa que retorna uma lista de string. Ainda não vimos uma tarefa com retorno, mas isto é possível, sendo do mesmo
             * tipo, porém genérico. Vamos utilizá-la como uma lista. Teremos uma task e, entre os sinais de maior e menor, indicamos o
             * retorno da tarefa correspondente, no caso, uma lista de string.
             */
            var resultado = new List <string>();

            var tasks = contas.Select(conta => {
                //estou criando uma task por conta cliente.
                return(Task.Factory.StartNew(() => {
                    /*
                     *  Sempre que temos uma tarefa encadeando outra, por parâmetro, recebemos a tarefa anterior, finalizada.
                     */
                    var contaResulado = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(contaResulado);
                }));
            });


            /* SOBRECARGA continueWith: a primeira devolve uma task, a segunda um tipo generico
             * Como retornaremos uma tarefa que por sua vez retorna uma lista e que, na verdade, precisa esperar todas as outras tarefas?
             * O WhenAll já vai esperar a execução de todas as tarefas. E ainda temos o método ContinueWith, o qual possibilita duas
             * sobrecargas: uma normal, que retorna uma task, e outra genérica, que retorna uma task com retorno de tipo genérico. Vamos
             * usar esta construção, e ela receberá um delegate, uma ação, que irá retornar o resultado. Como estamos executando esta tarefa de
             * forma encadeada em outra (aquela que espera todas as demais serem executadas), neste momento sabemos que o resultado está populado,
             * bastando retorná-lo.
             */

            //Quando todas as minhas tasks forem executados retornamos a lista de resultados.
            return(Task.WhenAll(tasks)  // O WhenAll vai esperar a execução de todas as tarefas.
                   .ContinueWith(t => { //temos o método ContinueWith, o qual possibilita duas sobrecargas: uma normal, que retorna uma task  e outra genérica, que retorna uma task com retorno de tipo genérico
                /* Sempre que temos uma tarefa encadeando outra, por parâmetro, recebemos a tarefa anterior, finalizada.
                 *
                 * Agora veremos por que isto é importante. Não se trata de uma tarefa qualquer, e sim com retorno de lista de string.
                 *
                 * Teremos portanto uma propriedade disponível chamada task.Result, pois as tarefas que possuem retorno são de classe genérica.
                 */
                return resultado;
            }));
        }
コード例 #16
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> reportadorDeProgresso, CancellationToken ct)
        {
            var tasks = contas.Select(conta =>
                                      Task.Factory.StartNew(() =>
            {
                // Ponto em que o usuário pode clicar em cancelar
                // foi escolhido essa posição pois ela antecede um processo pesado que no caso é o
                // Consolidar Movimentação, o mesmo foi feito para os outros lugares
                ct.ThrowIfCancellationRequested();

                var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta, ct);

                reportadorDeProgresso.Report(resultadoConsolidacao);

                ct.ThrowIfCancellationRequested();

                return(resultadoConsolidacao);
            })
                                      );

            return(await Task.WhenAll(tasks));
        }
コード例 #17
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> reportadorDeProgresso, CancellationToken ct)
        {
            var tasks = contas.Select(conta => Task.Factory.StartNew(() =>
            {
                ct.ThrowIfCancellationRequested();

                var resultadoConsolidação = r_Servico.ConsolidarMovimentacao(conta);
                reportadorDeProgresso.Report(resultadoConsolidação);
                ct.ThrowIfCancellationRequested();

                return(resultadoConsolidação);
            }, ct)

                                      );

            var resultado = await Task.WhenAll(tasks);


            return(resultado);

            #region old way
            //    var resultado = new List<string>();
            //    var tasks = contas.Select(conta =>
            //    {
            //        return Task.Factory.StartNew(()=>
            //        {
            //        var contaResultado = r_Servico.ConsolidarMovimentacao(conta);
            //        resultado.Add(contaResultado);
            //    });
            //});


            //    return Task.WhenAll(tasks).ContinueWith(t=>
            //        {
            //            return resultado;
            //        });
            #endregion
        }
コード例 #18
0
        private async Task <string[]> ConsolidarContas(IEnumerable <ContaCliente> contas, IProgress <string> reportadorDeProgresso, CancellationToken ct)
        {
            var taskSchedulerGUI = TaskScheduler.FromCurrentSynchronizationContext();
            var tasks            = contas.Select(conta =>
                                                 Task.Factory.StartNew(() =>
            {
                //if (ct.IsCancellationRequested)
                //    throw new OperationCanceledException(ct);
                ct.ThrowIfCancellationRequested();

                var resultadoConsolidacao = r_Servico.ConsolidarMovimentacao(conta, ct);
                reportadorDeProgresso.Report(resultadoConsolidacao);

                //if (ct.IsCancellationRequested)
                //    throw new OperationCanceledException(ct);
                ct.ThrowIfCancellationRequested();

                return(resultadoConsolidacao);
            }, ct)
                                                 );

            return(await Task.WhenAll(tasks));
        }
コード例 #19
0
        private void BtnProcessar_Click(object sender, RoutedEventArgs e)
        {
            var contas = r_Repositorio.GetContaClientes();

            var contasQuantidadePorThread = contas.Count() / 4;

            var contas_parte1 = contas.Take(contasQuantidadePorThread);
            var contas_parte2 = contas.Skip(contasQuantidadePorThread).Take(contasQuantidadePorThread);
            var contas_parte3 = contas.Skip(contasQuantidadePorThread * 2).Take(contasQuantidadePorThread);
            var contas_parte4 = contas.Skip(contasQuantidadePorThread * 3);

            var resultado = new List <string>();

            AtualizarView(new List <string>(), TimeSpan.Zero);

            var inicio = DateTime.Now;

            Thread thread_parte1 = new Thread(() =>
            {
                foreach (var conta in contas_parte1)
                {
                    var resultadoProcessamento = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoProcessamento);
                }
            });
            Thread thread_parte2 = new Thread(() =>
            {
                foreach (var conta in contas_parte2)
                {
                    var resultadoProcessamento = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoProcessamento);
                }
            });
            Thread thread_parte3 = new Thread(() =>
            {
                foreach (var conta in contas_parte3)
                {
                    var resultadoProcessamento = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoProcessamento);
                }
            });
            Thread thread_parte4 = new Thread(() =>
            {
                foreach (var conta in contas_parte4)
                {
                    var resultadoProcessamento = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoProcessamento);
                }
            });

            thread_parte1.Start();
            thread_parte2.Start();
            thread_parte3.Start();
            thread_parte4.Start();

            while (thread_parte1.IsAlive || thread_parte2.IsAlive ||
                   thread_parte3.IsAlive || thread_parte4.IsAlive)
            {
                Thread.Sleep(250);
                //Não vou fazer nada
            }

            var fim = DateTime.Now;

            AtualizarView(resultado, fim - inicio);
        }
コード例 #20
0
        private void BtnProcessar_Click(object sender, RoutedEventArgs e)
        {
            var contas = r_Repositorio.GetContaClientes();

            var contasQuantidadePorThread = contas.Count() / 4;

            // Armazena em um IEnumerable os N Primeiros Elementos da Lista
            var contas_parte1 = contas.Take(contasQuantidadePorThread);
            var contas_parte2 = contas.Skip(contasQuantidadePorThread).Take(contasQuantidadePorThread);
            var contas_parte3 = contas.Skip(contasQuantidadePorThread * 2).Take(contasQuantidadePorThread);
            var contas_parte4 = contas.Skip(contasQuantidadePorThread * 3);


            var resultado = new List <string>();

            AtualizarView(new List <string>(), TimeSpan.Zero);

            Thread thread_parte1 = new Thread(() =>
            {
                foreach (var conta in contas_parte1)
                {
                    var resultadoConta = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoConta);
                }
            });


            Thread thread_parte2 = new Thread(() =>
            {
                foreach (var conta in contas_parte2)
                {
                    var resultadoConta = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoConta);
                }
            });

            Thread thread_parte3 = new Thread(() =>
            {
                foreach (var conta in contas_parte3)
                {
                    var resultadoConta = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoConta);
                }
            });

            Thread thread_parte4 = new Thread(() =>
            {
                foreach (var conta in contas_parte4)
                {
                    var resultadoConta = r_Servico.ConsolidarMovimentacao(conta);
                    resultado.Add(resultadoConta);
                }
            });

            var inicio = DateTime.Now;

            thread_parte1.Start();
            thread_parte2.Start();
            thread_parte3.Start();
            thread_parte4.Start();

            while (thread_parte1.IsAlive || thread_parte2.IsAlive || thread_parte3.IsAlive || thread_parte4.IsAlive)
            {
                // Pausa a thread principal por alguns millisegundos para que a condição acima não seja verificada a todo momento
                Thread.Sleep(250);
                // Enquanto as threads estiverem trabalhando não faço nada
            }

            var fim = DateTime.Now;

            AtualizarView(resultado, fim - inicio);
        }
コード例 #21
0
        /// Clicaremos em "Fazer Processamento" no ByteBank. Lembrem-se que no vídeo anterior só havia um núcleo em funcionamento (CPU 0), e agora temos
        /// mais um. Ou seja, provavelmente o primeiro que estava sendo utilizado está executando uma thread da aplicação, e o outro (CPU 1), a outra thread.
        /// Desta forma, teoricamente, a aplicação rodará mais rapidamente - mas isto não é uma regra. Muitos fatores influenciam a velocidade de execução de
        /// uma aplicação: o sistema operacional pode estar aguardando respostas da rede, tentando ler o disco rígido, entre outros.

        private void BtnProcessar_Click(object sender, RoutedEventArgs e)
        {
            this.Cursor = Cursors.Wait;

            /*
             * O erro ocorreu porque estávamos na thread principal, atualizando a lista de resultados (LstResultados) e o texto de resumo (TxtTempo.Text = mensagem)
             * na mesma thread. Colocamos os códigos criados agora em uma diferente, sem saber qual, cuja responsabilidade não é nossa. Uma thread diferente não pode
             * acessar o controle da interface gráfica. O .NET protege isto, e quando uma tentativa de acesso a um objeto da interface gráfica ocorre por uma
             * thread diferente, a aplicação é travada, lançando-se a exceção.
             *
             * É necessário informar ao .NET que o código recém criado será executado na interface gráfica, sem ser necessário esperar todas as outras,
             * mantendo-se a interface gráfica travada até que a execução do código. Lembra que tínhamos um intermediário responsável por delegar quem
             * executaria qual tarefa, delegando assegurando que todas as threads fossem executadas da forma mais otimizada possível?
             *
             * O  TaskScheduler também existe na thread principal, sendo obtido a partir de uma que estiver em execução, com o método estático
             * FromCurrentSynchronizationContext(), que retorna o TaskScheduler atuante no momento.
             *
             * Assim, informamos ao .NET nosso desejo de que a tarefa referente à finalização e atualização de visualização seja feita de acordo com a demanda do
             * TaskScheduler, podendo ser enviado no método ContinueWith, como um parâmetro.
             */

            //Agora esta no contexto da thread principal, se eu mudado para dentro de uma thread lá sera o novo contexto.
            var taskSchedulerUI = TaskScheduler.FromCurrentSynchronizationContext();

            BtnProcessar.IsEnabled = false;


            //Obtem as contas do usuarios
            var contas = r_Repositorio.GetContaClientes();
            // a porção para cada thread processar
            var contasQuantidadePorThread = contas.Count() / 4;


            //Atualiza a lista
            AtualizarView(new List <string>(), TimeSpan.Zero);
            //Inicio do processamento
            var inicio = DateTime.Now;


            /*=================================
             * -- TaskScheduler ---------------
             * ================================
             * É gestor de tarefas do .Net. Agora nao precisamos mais nos preocuprar a performance das Threads,
             * ou quais sao as boas praticas. O task e excutado em um alto niveil. Thread baixo nivel. OS.
             *
             * Se há 10 contas sendo executadas simultaneamente, e 8 núcleos, sendo que um deles está parado, o TaskScheduler coloca-o para trabalhar.
             * Não precisamos mais nos preocupar em dividir tarefas para cada thread, pois ele faz isto. Quando usamos a Factory, propriedade estática
             * da classe Task, utilizamos o TaskScheduler default que o .NET nos fornece.
             */
            var contasTarefa = contas.Select(conta => {
                // Task ("tarefa" em inglês). Ele possui uma propriedade estática, Factory, que constrói tarefas. Nossa nova tarefa é constituída
                //por outra expressão lambda, a qual não recebe nenhum parâmetro, em que faremos a consolidação desta conta.
                return(Task.Factory.StartNew(() => {
                    var resultado = r_Servico.ConsolidarMovimentacao(conta);
                    resultados.Add(resultado);
                }));
            }).ToArray();

            /*
             * To Array
             * Relembremos que Select é uma função do LINQ, que age de forma mais "preguiçosa" possível. Neste momento, na execução da próxima
             * linha: var fim = DateTime.Now;. Nenhuma tarefa foi criada, pois o LINQ executa queries somente quando necessário. Se não usamos
             * a variável contasTarefas, o código que vem a seguir não é executado. Vamos forçar todas as tarefas a serem criadas, gerando um
             * array (.ToArray();) e obrigando o LINQ a executá-las:
             */


            /* WaitAll: Nao faça nada até que as todas as threads tenham sido executadas:
             * Por isso, criaremos um laço de repetição while para verificar se a thread IsAlive... Não nos preocupamos mais com threads,
             * tampouco com esta propriedade. Faremos isto de um jeito diferente: o Task possui um método estático chamado WaitAll que não faz
             * nada até que todas as outras tarefas sejam finalizadas. Este método recebe uma lista de tarefas como parâmetro, travando a
             * execução deste até que todas as tarefas terminem.
             */
            //Task.WaitAll(contasTarefa);

            /*
             * No momento em que se alcança o código Task.WaitAll(contasTarefas), a aplicação é pausada, e as linhas seguintes - de finalização e atualização da tela
             * - só serão executadas quando terminarmos todas as tarefas existentes. Verificaremos seu funcionamento apertando "Start" mais uma vez e acompanhando
             * o uso das CPUs pelo Gerenciador de Tarefas.*/

            //com o whenAll conseguimos encadear outras tarefas.
            Task.WhenAll(contasTarefa)
            .ContinueWith(task => {
                //Parametro task:dentro do corpo da função temos disponível a task que originou a execução.. Ou seja, a task será a tarefa que espera todas as outras (Task.WhenAll())
                //Termino do processamento
                var fim = DateTime.Now;
                AtualizarView(resultados, fim - inicio);

                //Não podemos alterar um objeto da interface gráfica a partir de outras Threads por isso eu preciso do contexto da thread UI(princiual)
                //que esta no objecto taskSchedulerUI;
                BtnProcessar.IsEnabled = true;
            }, taskSchedulerUI);


            this.Cursor = Cursors.Arrow;
        }