Xamarins表单中的异步调用

时间:2016-07-22 16:52:39

标签: c# android xamarin xamarin.forms

我正在使用Xamarin Forms C#向Android中的SQLite导入数据,我遇到了这个问题。

要进行数据导入,我正在使用我开发的API,每个表都有一个链接,在这种情况下,我导入5个表,每个表大约有1.000个记录,我需要制作5个调用(调用Table1API,调用Table2API,调用Table3API,调用Table4API,调用Table5API)

这是正常的,但在DDMS中显示此错误,“I / Choreographer(1273):跳过259帧!应用程序可能在其主线程上做了太多工作”并且应用程序崩溃。

我做错了什么?

按照链接提供帮助:

Methos和按钮点击事件: https://1drv.ms/u/s!AlRdq6Nx4CD6g4ouw1F1KJzmnfx5zg

我使用API​​的方法:

public async Task<string> ConsumeRestAPI(string url, string tkn)
{
    url += "?" + tkn;
    string retString = string.Empty;

    try
    {
        using (var client = new HttpClient())
        {
            var result = await client.GetAsync(url);
            retString = await result.Content.ReadAsStringAsync();
        }
    }
    catch (Exception ex)
    {
        retString = ex.Message + "\n\nErro ao tentar se conectar com o servidor.";
    }

    return retString;
}

方法和按钮点击事件:

private async Task AsyncTaskTPRE(string pSYNC_DescTabela, string pSYNC_NomeTabela)
    {
        string pUrl = string.Empty;
        string content = string.Empty;
        string jsonMsgError = string.Empty;
        int qtdReg = 0;

        ServiceWrapper sw = new ServiceWrapper();
        JArray jsonArray = null;

        if (!actLoading.IsRunning)
            actLoading.IsRunning = true;
        lblTitulo.Text = "Conectando à API...";

        pUrl = pAPIURL + "TabelaPrecoAPI.aspx";
        content = await sw.ConsumeRestAPI(pUrl, pAPITKN);

        if (!ErroRetornoJSON(content, pSYNC_DescTabela, out jsonMsgError))
        {
            #region Importação tbTPRE

            content = sw.Html2JSON(content);
            jsonArray = JArray.Parse(content);
            qtdReg = 1;

            foreach (var itemJSON in jsonArray)
            {
                PreencherTPRE(itemJSON);

                lblTitulo.FontSize = 12;
                lblTitulo.HorizontalOptions = LayoutOptions.Start;
                lblTitulo.VerticalOptions = LayoutOptions.Start;

                lblTitulo.Text = "Importando " + "\"" + pSYNC_DescTabela + "\"...\n"
                    + " (Registro " + qtdReg.ToString() + " de " + jsonArray.Count() + " importado(s))";
                await Task.Delay(10);

                TPRE TPRE_Atual = pTPRE.GetTPRE(objTPRE.TPRE_Codigo, objTPRE.TPRE_SQEM_Id);
                if (TPRE_Atual == null)
                {
                    pTPRE.Insert(objTPRE);
                    if (pTPRE.HasError)
                    {
                        await DisplayAlert("Error", "Erro ao importar registro da tabela " + pSYNC_DescTabela + "!\n"
                            + "ID do Registro: " + objTPRE.TPRE_Id + "\n"
                            + "Erro: " + pTPRE.MsgError, "OK");
                        break;
                    }
                }
                else
                {
                    pTPRE.Update(objTPRE);
                    if (pTPRE.HasError)
                    {
                        await DisplayAlert("Error", "Erro ao atualizar registro da tabela " + pSYNC_DescTabela + "!\n"
                            + "ID do Registro: " + objTPRE.TPRE_Id + "\n"
                            + "Erro: " + pTPRE.MsgError, "OK");
                        break;
                    }
                }

                qtdReg++;
            }

            #endregion

            #region Insert/Update tbSYNC

            SYNC objSYNC = pSYNC.GetSYNC(pSYNC_NomeTabela);
            if (objSYNC == null)
            {
                objSYNC = new SYNC()
                {
                    SYNC_NomeTabela = pSYNC_NomeTabela,
                    SYNC_DescTabela = pSYNC_DescTabela,
                    SYNC_DataImportSync = DateTime.Now,
                    SYNC_DataExportSync = null,
                    CreatedBy = string.Empty,
                    CreatedOn = DateTime.Now,
                    UpdatedBy = string.Empty,
                    UpdatedOn = DateTime.Now
                };

                pSYNC.Insert(objSYNC);
                if (pSYNC.HasError)
                {
                    await DisplayAlert("Error", "Erro ao incluir registro na tabela de sincronização!\n" + pSYNC.MsgError, "OK");
                }
            }
            else
            {
                objSYNC.SYNC_DataImportSync = DateTime.Now;
                objSYNC.UpdatedBy = string.Empty;
                objSYNC.UpdatedOn = DateTime.Now;

                pSYNC.Update(objSYNC);
                if (pSYNC.HasError)
                {
                    await DisplayAlert("Error", "Erro ao atualizar registro na tabela de sincronização!\n" + pSYNC.MsgError, "OK");
                }
            }

            #endregion
        }
        else
        {
            await DisplayAlert("Atenção", jsonMsgError, "OK");
        }
    }

    private async Task AsyncTaskITTP(string pSYNC_DescTabela, string pSYNC_NomeTabela)
    {
        string pUrl = string.Empty;
        string content = string.Empty;
        string jsonMsgError = string.Empty;
        int qtdReg = 0;

        ServiceWrapper sw = new ServiceWrapper();
        JArray jsonArray = null;

        if (!actLoading.IsRunning)
            actLoading.IsRunning = true;

        lblTitulo.Text = "Conectando à API...";
        pUrl = pAPIURL + "ItensTabelaPrecoAPI.aspx";
        content = await sw.ConsumeRestAPI(pUrl, pAPITKN);

        if (!ErroRetornoJSON(content, pSYNC_DescTabela, out jsonMsgError))
        {
            #region Importação tbITTP

            content = sw.Html2JSON(content);
            jsonArray = JArray.Parse(content);
            qtdReg = 1;

            foreach (var ITTPjson in jsonArray)
            {
                PreencherITTP(ITTPjson);

                lblTitulo.FontSize = 12;
                lblTitulo.HorizontalOptions = LayoutOptions.Start;
                lblTitulo.VerticalOptions = LayoutOptions.Start;

                lblTitulo.Text = "Importando " + "\"" + pSYNC_DescTabela + "\"...\n"
                    + " (Registro " + qtdReg.ToString() + " de " + jsonArray.Count() + " importado(s))";
                await Task.Delay(10);

                ITTP ITTP_Atual = pITTP.GetITTP(objITTP.ITTP_Id);
                if (ITTP_Atual == null)
                {
                    pITTP.InsertWithChildren(objITTP);
                    if (pITTP.HasError)
                    {
                        await DisplayAlert("Error", "Erro ao importar registro da tabela " + pSYNC_DescTabela + "!\n"
                            + "ID do Registro: " + objITTP.ITTP_Id + "\n"
                            + "Erro: " + pITTP.MsgError, "OK");
                        break;
                    }
                }
                else
                {
                    pITTP.UpdateWithChildren(objITTP);
                    if (pITTP.HasError)
                    {
                        await DisplayAlert("Error", "Erro ao atualizar registro da tabela " + pSYNC_DescTabela + "!\n"
                            + "ID do Registro: " + objITTP.ITTP_Id + "\n"
                            + "Erro: " + pITTP.MsgError, "OK");
                        break;
                    }
                }

                qtdReg++;
            }

            #endregion

            #region Insert/Update tbSYNC

            SYNC objSYNC = pSYNC.GetSYNC(pSYNC_NomeTabela);
            if (objSYNC == null)
            {
                objSYNC = new SYNC()
                {
                    SYNC_NomeTabela = pSYNC_NomeTabela,
                    SYNC_DescTabela = pSYNC_DescTabela,
                    SYNC_DataImportSync = DateTime.Now,
                    SYNC_DataExportSync = null,
                    CreatedBy = string.Empty,
                    CreatedOn = DateTime.Now,
                    UpdatedBy = string.Empty,
                    UpdatedOn = DateTime.Now
                };

                pSYNC.Insert(objSYNC);
                if (pSYNC.HasError)
                {
                    await DisplayAlert("Error", "Erro ao incluir registro na tabela de sincronização!\n" + pSYNC.MsgError, "OK");
                }
            }
            else
            {
                objSYNC.SYNC_DataImportSync = DateTime.Now;
                objSYNC.UpdatedBy = string.Empty;
                objSYNC.UpdatedOn = DateTime.Now;

                pSYNC.Update(objSYNC);
                if (pSYNC.HasError)
                {
                    await DisplayAlert("Error", "Erro ao atualizar registro na tabela de sincronização!\n" + pSYNC.MsgError, "OK");
                }
            }

            #endregion
        }
        else
        {
            await DisplayAlert("Atenção", jsonMsgError, "OK");
        }
    }

    private async Task AsyncTaskPLPG(string pSYNC_DescTabela, string pSYNC_NomeTabela)
    {
        string pUrl = string.Empty;
        string content = string.Empty;
        string jsonMsgError = string.Empty;
        int qtdReg = 0;

        ServiceWrapper sw = new ServiceWrapper();
        JArray jsonArray = null;

        if (!actLoading.IsRunning)
            actLoading.IsRunning = true;

        lblTitulo.Text = "Conectando à API...";
        pUrl = pAPIURL + "PlanoPagamentoAPI.aspx";
        content = await sw.ConsumeRestAPI(pUrl, pAPITKN);

        if (!ErroRetornoJSON(content, pSYNC_DescTabela, out jsonMsgError))
        {
            #region Importação tbPLPG

            content = sw.Html2JSON(content);
            jsonArray = JArray.Parse(content);
            qtdReg = 1;

            foreach (var PLPGjson in jsonArray)
            {
                PreencherPLPG(PLPGjson);

                lblTitulo.FontSize = 12;
                lblTitulo.HorizontalOptions = LayoutOptions.Start;
                lblTitulo.VerticalOptions = LayoutOptions.Start;

                lblTitulo.Text = "Importando " + "\"" + pSYNC_DescTabela + "\"...\n"
                    + " (Registro " + qtdReg.ToString() + " de " + jsonArray.Count() + " importado(s))";
                await Task.Delay(10);

                PLPG PLPG_Atual = pPLPG.GetPLPG(objPLPG.PLPG_Id);
                if (PLPG_Atual == null)
                {
                    pPLPG.Insert(objPLPG);
                    if (pPLPG.HasError)
                    {
                        await DisplayAlert("Error", "Erro ao importar registro da tabela " + pSYNC_DescTabela + "!\n"
                            + "ID do Registro: " + objPLPG.PLPG_Id + "\n"
                            + "Erro: " + pPLPG.MsgError, "OK");
                        break;
                    }
                }
                else
                {
                    pPLPG.Update(objPLPG);
                    if (pPLPG.HasError)
                    {
                        await DisplayAlert("Error", "Erro ao atualizar registro da tabela " + pSYNC_DescTabela + "!\n"
                            + "ID do Registro: " + objPLPG.PLPG_Id + "\n"
                            + "Erro: " + pPLPG.MsgError, "OK");
                        break;
                    }
                }

                qtdReg++;
            }

            #endregion

            #region Insert/Update tbSYNC

            SYNC objSYNC = pSYNC.GetSYNC(pSYNC_NomeTabela);
            if (objSYNC == null)
            {
                objSYNC = new SYNC()
                {
                    SYNC_NomeTabela = pSYNC_NomeTabela,
                    SYNC_DescTabela = pSYNC_DescTabela,
                    SYNC_DataImportSync = DateTime.Now,
                    SYNC_DataExportSync = null,
                    CreatedBy = string.Empty,
                    CreatedOn = DateTime.Now,
                    UpdatedBy = string.Empty,
                    UpdatedOn = DateTime.Now
                };

                pSYNC.Insert(objSYNC);
                if (pSYNC.HasError)
                {
                    await DisplayAlert("Error", "Erro ao incluir registro na tabela de sincronização!\n" + pSYNC.MsgError, "OK");
                }
            }
            else
            {
                objSYNC.SYNC_DataImportSync = DateTime.Now;
                objSYNC.UpdatedBy = string.Empty;
                objSYNC.UpdatedOn = DateTime.Now;

                pSYNC.Update(objSYNC);
                if (pSYNC.HasError)
                {
                    await DisplayAlert("Error", "Erro ao atualizar registro na tabela de sincronização!\n" + pSYNC.MsgError, "OK");
                }
            }

            #endregion
        }
        else
        {
            await DisplayAlert("Atenção", jsonMsgError, "OK");
        }
    }

private async void BtnImport_Clicked(object sender, EventArgs e)
{
        List<SYNC> listSYNC = lvwTabelas.ItemsSource.Cast<SYNC>().ToList();
        bool confirmacaoProcessamento = false;

        PopularStatusConexao();

        #region Validação de Campos/Parâmetros

        var regSelecionado = listSYNC.Where(s => s.SYNC_IsToggled).Any();
        if (!regSelecionado)
        {
            await DisplayAlert("Atenção", "Selecione pelo menos uma tabela para importar!", "OK");
        }
        else if (!pConnStatus)
        {
            await DisplayAlert("Atenção", "Sem conexão com internet!\nPara prosseguir com o processamento é necessário que esteja conectado em alguma rede.", "OK");
        }
        else if (!pConnWifiStatus)
        {
            var confirm = await DisplayAlert("Confirmação", "Para prosseguir com o processo de importação, recomendamos "
                + "que esteja conectado em uma rede WiFi.\n\nDeseja prosseguir?", "Sim", "Não");

            confirmacaoProcessamento = confirm;
        }
        else if (pAPIURL == string.Empty)
        {
            await DisplayAlert("Atenção", "Parâmetro \"URL\" inválido!\nVerifique o parâmetro na parametrização da API.", "OK");
        }
        else if (pAPITKN == string.Empty)
        {
            await DisplayAlert("Atenção", "Parâmetro \"Token\" inválido!\nVerifique o parâmetro na parametrização da API.", "OK");
        }
        else
        {
            var confirm = await DisplayAlert("Confirmação", "Para prosseguir com o processo de importação, recomendamos "
                + "que esteja conectado em uma rede WiFi, atualmente você possui essa conexão.\n\nDeseja prosseguir?", "Sim", "Não");

            confirmacaoProcessamento = confirm;
        }

        #endregion

        #region Operação

        if (confirmacaoProcessamento)
        {
            lvwTabelas.IsEnabled = false;
            btnImport.IsEnabled = false;
            swtSelecionarTodos.IsVisible = false;

            listSYNC = listSYNC.Where(s => s.SYNC_IsToggled).ToList();
            foreach (var item in listSYNC)
            {
                //int pPEFJ_Codigo = 0;
                //int pPEFJ_SQEM_Id = 0;

                #region Importação de Tabelas

                switch (item.SYNC_NomeTabela)
                {
                    #region tbPEFJ - Pessoa Física/Jurídica

                    case "tbPEFJ":
                        await AsyncTaskPEFJ(item.SYNC_DescTabela, item.SYNC_NomeTabela);

                        break;

                    #endregion

                    #region tbPROD - Produtos

                    case "tbPROD":
                        //qtdReg = 1;

                        //lblTitulo.FontSize = 15;
                        //lblTitulo.HorizontalOptions = LayoutOptions.Start;
                        //lblTitulo.Text = "Importando " + "\"" + item.SYNC_DescTabela + "\"...";
                        //await Task.Delay(1000);

                        break;

                    #endregion

                    //

                    #region tbTPRE - Tabela de Preço

                    case "tbTPRE":
                        await AsyncTaskTPRE(item.SYNC_DescTabela, item.SYNC_NomeTabela);

                        break;

                    #endregion

                    #region tbITTP - Itens da Tabela de Preço

                    case "tbITTP":
                        await AsyncTaskITTP(item.SYNC_DescTabela, item.SYNC_NomeTabela);

                        break;

                    #endregion

                    #region tbPLPG - Plano de Pagamento

                    case "tbPLPG":
                        await AsyncTaskPLPG(item.SYNC_DescTabela, item.SYNC_NomeTabela);

                        break;

                    #endregion

                    #region tbFOPG - Forma de Pagamento

                    case "tbFOPG":
                        await AsyncTaskFOPG(item.SYNC_DescTabela, item.SYNC_NomeTabela);

                        break;

                    #endregion

                    //

                    #region tbPEDI - Pedidos

                    case "tbPEDI":
                        //lblTitulo.FontSize = 15;
                        //lblTitulo.HorizontalOptions = LayoutOptions.Start;
                        //lblTitulo.Text = "Importando " + "\"" + item.SYNC_DescTabela + "\"...";
                        //await Task.Delay(1000);

                        break;

                    #endregion

                    #region tbITPD - Itens do Pedido

                    case "tbITPD":
                        //lblTitulo.FontSize = 15;
                        //lblTitulo.HorizontalOptions = LayoutOptions.Start;
                        //lblTitulo.Text = "Importando " + "\"" + item.SYNC_DescTabela + "\"...";
                        //await Task.Delay(1000);

                        break;

                    #endregion

                    default:
                        break;
                }

                #endregion
            }

            swtSelecionarTodos.IsVisible = true;
            actLoading.IsRunning = false;

            //if (!erroProc)
            //    await DisplayAlert("Aviso", "Importação realizada com sucesso!", "OK");

            lblTitulo.FontSize = 22;
            lblTitulo.Text = "Importação de Tabelas";
            lblTitulo.HorizontalOptions = LayoutOptions.Center;

            lvwTabelas.IsEnabled = true;
            btnImport.IsEnabled = true;

            Popular_lvwTabelas();
            PopularStatusConexao();
        }

        #endregion
    }

1 个答案:

答案 0 :(得分:1)

当您单击该按钮时,似乎您实际上并未启动新线程。如果是这样,所有工作都在主线程上完成,因此可能导致错误。要启动新线程,您需要调用Task.Run(...)或使用其他实际启动新线程的API。代码是,除非我错过它,否则你永远不会开始新的线程。你等待其他一些异步操作,即DisplayAlert,但因为你从不使用Task.ConfigureAwait(false),所以你总是被返回到主线程。 IOW如果在调用您正在等待的第一个异步方法时,您执行以下操作(在AsyncTaskTPRE方法中):

content = await sw.ConsumeRestAPI(pUrl, pAPITKN).ConfigureAwait(false);

当该方法返回时,您将不再位于UI /主线程上。当该方法返回时,如果没有ConfigureAwait(false),则返回主线程,因为ConfigureAwait(...)的默认值为true。

请参阅MS关于使用async的指南并等待:https://msdn.microsoft.com/en-us/library/mt674882.aspx

在标题为“线程”的部分中,它说明如下:

  

async和await关键字不会导致创建其他线程。异步方法不需要多线程,因为异步方法不能在自己的线程上运行。该方法在当前同步上下文上运行,并仅在方法处于活动状态时在线程上使用时间。您可以使用Task.Run将受CPU限制的工作移动到后台线程,但后台线程对于只等待结果可用的进程没有帮助。