简体   繁体   中英

Async Calls in Xamarins Forms

I'm making an data import to SQLite in Android, using Xamarin Forms C#, and I have problems with this.

To make the data import, i'm using an API, that I developed, and each table has a link, in this case, I'm importing 5 tables, with aproximately 1.000 records each table, I need to make 5 calls (call Table1API, call Table2API, call Table3API, call Table4API, call Table5API)

This is working correctly, but showing this error in DDMS, "I/Choreographer(1273): Skipped 259 frames! The application may be doing too much work on its main thread" and the app crash.

What am I doing wrong?

Follow links to help:

Methos, and button click event: https://1drv.ms/u/s!AlRdq6Nx4CD6g4ouw1F1KJzmnfx5zg

My Method to consume 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;
}

Methods and button clicked event:

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
    }

It seems you are not actually launching a new thread when you click that button. And if so, all that work is being done on the main thread, hence perhaps causing the error. To start a new thread, you do need to call Task.Run(...) or use some other API that will actually start a new thread. As the code is, unless I am missing it, you never start a new thread. You do await some other async operations, ie DisplayAlert but because you never use Task.ConfigureAwait(false) you are always being returned to the main thread. IOW if when calling the first async method that you are awaiting, you do the following (in the AsyncTaskTPRE method):

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

when that method returns, you will not be on the UI/Main thread anymore. Without ConfigureAwait(false) when that method returns you are back on the main thread as the default for ConfigureAwait(...) is true.

See MS's guide on using async and await: https://msdn.microsoft.com/en-us/library/mt674882.aspx

In the section titled "Threads" it says the following:

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use Task.Run to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available.

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