none
UI Threads WPF RRS feed

  • Pergunta

  • Estou enfrentando dificuldades para gerenciar a interface enquanto realizo uma requisição remota.

    Preciso exibir um progress dialog que é, na verdade, um user control que já está incluido no formulário principal, entretanto oculto. 

    No momento do clique do botão no cadastro, exibo o uc e simultaneamente faço uma requisição ao web service, neste momento a interface trava aguardando o retorno da requisição.

    Já tentei utilizar a thread normal^

    Thread thread = new Thread(meuMetodo);

    thread.start();

    Já tentei utilizar também o BackgroundWorker.

    Sugestões?

    terça-feira, 18 de setembro de 2012 19:27

Respostas

  • Aline, acho que falei coisa errada.
    Na verdade o Dispatcher tem que ficar fora do método da Thread, após o Start.
    Aí dentro do método da Thread após executar a requisição vc oculta o carregamento lá mesmo.


    Thread t = new Thread(executaTarefa);
    t.Start();

    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
    {
     ucAlerta.mostrarCarregando("", "Carregando");
    }));


    public void executaTarefa()
    {

    //Executa a requisição


    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
                {
                    ucAlerta.ocultarCarregando("", "Carregando");
                })); 

    //finaliza a Thread.
    t.Abort();

    }

    Victor Camargos

    • Marcado como Resposta Aline Diesel quinta-feira, 20 de setembro de 2012 17:39
    quinta-feira, 20 de setembro de 2012 16:40

Todas as Respostas

  • Dê uma estudada no código de exemplo que eu postei no code gallery:

    http://code.msdn.microsoft.com/Async-Await-Using-Visual-3382e80a

    Acho que a melhor maneira é fazer uma Action e rodar em outro Thread a consulta ao WCF. Mas na hora de exibir o UC e ocultar o UC, vai ter de fazer usando o Dispatcher.

    quarta-feira, 19 de setembro de 2012 04:35
  • Oi.

    Já havia tentado fazer com a action. Trava a interface de qualquer.

    O que consegui ontem mais ou menos foi trabalhar dessa forma:

    BackgroundWorker requisicaoLogin = new BackgroundWorker();
                    requisicaoLogin.DoWork += b_DoWork;
                    requisicaoLogin.RunWorkerAsync(txtUsuario.Text);
                    requisicaoLogin.RunWorkerCompleted += b_RunWorkerCompleted;

    Entretanto, eu precisaria trabalhar com o retorno da requisição, mas pelo que li do evento complete, ele traz o complete, exception ou cancel. Eu teria que fazer um ajuste numa variavel global, por exemplo, pra poder trabalhar com o retorno. Não tá certo isso. Se tiver 4 requisições no mesmo formulário com retornos mesclando em objetos e tipos primitivos meu código não ficará mais limpo, além de ser uma péssima prática. =/

    quarta-feira, 19 de setembro de 2012 12:41
  • Ola.

    Como o Ucha citou, você terá que usar o Dispatcher para acessar o UC.

    Talves baste você inserir o código para exibir seu UC no inicio do método da sua Thread utilizando o Dispatcher:

    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>

                    {
                       //exibe seu UC de progresso
                    }

    E ao final do método da Thread vc oculta utilizando o mesmo trecho de código.

    Não sei se isso vai funcionar, acredito que sim.

    Espero ter ajudado.


    Victor Camargos

    quarta-feira, 19 de setembro de 2012 20:47
  • Acabei de testar desta forma, Victor. 

    Seria algo basicamente como isso:

     this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
                {
                    ucAlerta.mostrarCarregando("", "Carregando");
                }));

                string retornoRequisicao = Servicos.Requisicao.executarRequisicao(..)

    Correto?

    A reação que obtive nesta tentativa foi: ele executa a ação toda e depois mostra o uc.

    Ou seja, apenas no retorno da requisição, de qualquer forma. 

    Não trava a interface, de fato, por que nem chega a abrir o alerta antes da requisição. =T

    • Marcado como Resposta Aline Diesel quinta-feira, 20 de setembro de 2012 17:39
    • Não Marcado como Resposta Aline Diesel quinta-feira, 20 de setembro de 2012 17:39
    quinta-feira, 20 de setembro de 2012 12:54
  • Aline, acho que falei coisa errada.
    Na verdade o Dispatcher tem que ficar fora do método da Thread, após o Start.
    Aí dentro do método da Thread após executar a requisição vc oculta o carregamento lá mesmo.


    Thread t = new Thread(executaTarefa);
    t.Start();

    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
    {
     ucAlerta.mostrarCarregando("", "Carregando");
    }));


    public void executaTarefa()
    {

    //Executa a requisição


    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
                {
                    ucAlerta.ocultarCarregando("", "Carregando");
                })); 

    //finaliza a Thread.
    t.Abort();

    }

    Victor Camargos

    • Marcado como Resposta Aline Diesel quinta-feira, 20 de setembro de 2012 17:39
    quinta-feira, 20 de setembro de 2012 16:40
  • Funciona@ \o/

    É perfeito!

    Não trava a interface, não aguarda retorno de requisição... Excelente!

    Muitíssimo obrigada. (=

    Os procedimentos sugeridos:

    private void btnEntrar_MouseDown_1(object sender, MouseButtonEventArgs e)
            {
                try
                {
                    Thread th = new Thread(executarRequisicaoLogin);
                    th.Start();

                    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
                    {
                        alertaLoader.mostrarCarregando();
                        alertaLoader.uBtnFecharAlerta.Visibility = System.Windows.Visibility.Collapsed;
                    }));

    }
                catch (Exception)
                {
                    throw;
                }
            }


    private void executarRequisicaoLogin()
            {
                string retornoRequisicao = Servicos.Requisicao.executarRequisicao(...);
                Object objRetorno = (...)
                if (objRetorno.status)
                {
                    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
                    {
                        alertaLoader.mostrarSucesso("conectado");
                    }));
                }
                else
                {
                   
                }

    }

    quinta-feira, 20 de setembro de 2012 17:38