简体   繁体   English

APM模式,等待异步

[英]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. 我需要有关如何使用APM模式的帮助,我现在正在阅读一些文章,但是恐怕我没有太多时间。 What i really want is to get all the persons(data from db) then get the photos and put it on a autocompletebox Code: 我真正想要的是获取所有人员(来自db的数据),然后获取照片并将其放在autocompletebox代码中:

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 . listanomesautocomplete事件处理程序应为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). 处理并报告其中可能抛出的所有异常(通常,此规则适用于任何事件处理程序,但对于async事件处理程序而言更为重要,因为处理程序内部的异步操作会在触发该事件的代码范围之外继续进行) 。

  • Register the dlFotoCompleted event handler first, then call dlFotoAsync . 首先注册dlFotoCompleted事件处理程序,然后调用dlFotoAsync Do not assume that dlFotoAsync will be always executed asynchronously. 不要假设dlFotoAsync始终异步执行。

  • Think about the case when another listanomesautocomplete is fired while the previous operation is still pending. 考虑一下在上一个操作仍处于挂起状态listanomesautocomplete触发了另一个listanomesautocomplete的情况。 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. 回到问题,这是您需要包装为Task而不是APM的EAP模式 Use TaskCompletionSource for that. TaskCompletionSource使用TaskCompletionSource 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!! Noseratio,您的回答给了我一个主意,并且确实有效!! Thanks a lot man, i can't thank you enough ;) 非常感谢男人,我感激不尽;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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