简体   繁体   中英

APM pattern, Await Async

I need help on how to use APM pattern, i am now reading some articles, but i am afraid i don't have much time. What i really want is to get all the persons(data from db) then get the photos and put it on a autocompletebox Code:

void listanomesautocomplete(object sender, ServicosLinkedIN.queryCompletedEventArgs e)
        {
            if (e.Result[0] != "")
            {
                for (int i = 0; i < e.Result.Count(); i = i + 3)
                {
                    Pessoa pessoa = new Pessoa();
                    pessoa.Nome = e.Result[i];
                    pessoa.Id = Convert.ToInt32(e.Result[i + 1]);
                    if (e.Result[i + 2] == "")
                        pessoa.Imagem = new BitmapImage(new Uri("Assets/default_perfil.png", UriKind.Relative));
                    else
                    {
                        ServicosLinkedIN.ServicosClient buscaimg = new ServicosLinkedIN.ServicosClient();
                        buscaimg.dlFotoAsync(e.Result[i + 2]);
                        buscaimg.dlFotoCompleted += buscaimg_dlFotoCompleted;//when this completes it saves into a public bitmapimage and then i save it into pessoa.Imagem
                        //basicly, what happends, the listadlfotosasync only happends after this function
                        //what i want is to wait until it completes and have into the class novamsg
                        pessoa.Imagem = img;//saving the photo from dlFotoAsync           

                    }
                    listaPessoas.Add(pessoa);
                }

                tbA_destinatario.ItemsSource = null;
                tbA_destinatario.ItemsSource = listaPessoas;

                BackgroundWorker listapessoas = new BackgroundWorker();
                listapessoas.DoWork += listapessoas_DoWork;
                listapessoas.RunWorkerAsync();
                tb_lerdestmsg.Text = "";
            }
            else
            {
                tbA_destinatario.ItemsSource = null;
                tb_lerdestmsg.Text = "Não encontrado";
            }
        }

There are a few things to address here:

  • The listanomesautocomplete event handler should be async . Handle and report all exceptions possibly thrown inside it (generally, this rule applies to any event handler, but it's even more important for async event handlers, because the asynchronous operation inside your handler continues outside the scope of the code which has fired the event).

  • Register the dlFotoCompleted event handler first, then call dlFotoAsync . Do not assume that dlFotoAsync will be always executed asynchronously.

  • Think about the case when another listanomesautocomplete is fired while the previous operation is still pending. This well may happen as a result of the user's action. You may want to cancel and restart the pending operation (like this ), or just queue a new one to be executed as soon as the pending one has completed (like this ).

Back to the question, it's the EAP pattern that you need to wrap as Task , not APM. Use TaskCompletionSource for that. The relevant part of your code may look like this:

async void listanomesautocomplete(object sender, ServicosLinkedIN.queryCompletedEventArgs e)
{
    if (e.Result[0] != "")
    {
        for (int i = 0; i < e.Result.Count(); i = i + 3)
        {
            Pessoa pessoa = new Pessoa();
            pessoa.Nome = e.Result[i];
            pessoa.Id = Convert.ToInt32(e.Result[i + 1]);
            if (e.Result[i + 2] == "")
                pessoa.Imagem = new BitmapImage(new Uri("Assets/default_perfil.png", UriKind.Relative));
            else
            {
                // you probably want to create the service proxy 
                // outside the for loop
                using (ServicosLinkedIN.ServicosClient buscaimg = new ServicosLinkedIN.ServicosClient())
                {
                    FotoCompletedEventHandler handler = null;
                    var tcs = new TaskCompletionSource<Image>();

                    handler = (sHandler, eHandler) =>
                    {
                        try
                        {
                            // you can move the code from buscaimg_dlFotoCompleted here,
                            // rather than calling buscaimg_dlFotoCompleted
                            buscaimg_dlFotoCompleted(sHandler, eHandler);

                            tcs.TrySetResult(eHandler.Result);
                        }
                        catch (Exception ex)
                        {
                            tcs.TrySetException(ex);
                        }
                    };

                    try
                    {
                        buscaimg.dlFotoCompleted += handler;
                        buscaimg.dlFotoAsync(e.Result[i + 2]);

                        // saving the photo from dlFotoAsync
                        pessoa.Imagem = await tcs.Task;
                    }
                    finally
                    {
                        buscaimg.dlFotoCompleted -= handler;
                    }
                }
            }
            listaPessoas.Add(pessoa);
        }

        tbA_destinatario.ItemsSource = null;
        tbA_destinatario.ItemsSource = listaPessoas;

        BackgroundWorker listapessoas = new BackgroundWorker();
        listapessoas.DoWork += listapessoas_DoWork;
        listapessoas.RunWorkerAsync();
        tb_lerdestmsg.Text = "";
    }
    else
    {
        tbA_destinatario.ItemsSource = null;
        tb_lerdestmsg.Text = "Não encontrado";
    }
}
void listanomesautocomplete(object sender, ServicosLinkedIN.queryCompletedEventArgs e)
        {

            if (e.Result[0] != "")
            {

                List<Pessoa> listaPessoas = new List<Pessoa>();

                for (int i = 0; i < e.Result.Count(); i = i + 3)
                {
                    Pessoa pessoa = new Pessoa();
                    pessoa.Nome = e.Result[i];
                    pessoa.Id = Convert.ToInt32(e.Result[i + 1]);
                    if (e.Result[i + 2] == "")
                        pessoa.Imagem = new BitmapImage(new Uri("Assets/default_perfil.png", UriKind.Relative));
                    else
                    {
                        ServicosLinkedIN.ServicosClient buscaimg = new ServicosLinkedIN.ServicosClient();
                        buscaimg.dlFotoAsync(e.Result[i + 2]);
                        //THIS ACTUALLY WORKS!!!
                        //THE THREAD WAITS FOR IT!
                        buscaimg.dlFotoCompleted += (s, a) =>
                        {
                            pessoa.Imagem = ConvertToBitmapImage(a.Result);
                        };
                    }
                    listaPessoas.Add(pessoa);
                }

                if (tbA_destinatario.ItemsSource == null)
                {

                    tbA_destinatario.ItemsSource = listaPessoas;
                }
                tb_lerdestmsg.Text = "";
            }
            else
            {
                tbA_destinatario.ItemsSource = null;
                tb_lerdestmsg.Text = "Não encontrado";
            }
        }

Man, i am not even mad, i am amazed. Noseratio, you answer gave me an idea and it actually worked!! Thanks a lot man, i can't thank you enough ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM