Readdy Write  
0,00 €
Your View Money
Views: Count
Self 20% 0
Your Content 60% 0

Users by Links 0
u1*(Content+Views) 10% 0
Follow-Follower 0
s2*(Income) 5% 0

Count
Followers 0
Login Register as User
async ; await ;

C# : Async und Await Schleifen

02.07.2018 (👁6913)

Async und Await Schleifen in C#

Wenn man in C# eine Endlosschleife programmiert, dann muss man bei der Asynchronen Methode await einbauen.

Diese funktionieren aber nur, wenn man die aufzurufende Methode mit async Task<> definiert.

Beim Definieren der Asynchronen Methode mit async void  wird nicht auf echte asynchrone Vorgänge gewartet

Endlosschleife mit echtem await programmieren

1) Richtiger Async / Await  Aufbau

Richtig: mit await

Dieses kleine C# Code Beispiel enthält eine While-Endlosschleife, welche im innern auf das Ergebnis des Lesens einer Webseite wartet.

Der Aufruf erfolgt Asynchron mit dem Kürzel: await vor der Methode.

Das heißt, das Programm und auch der Debugger warten solange, bis der Aufruf der Methode zurückkommt.

//----< @Loop: Alle Empty Records >----

            while (1==1)

            

                //----< Detail >----

                if (optStop.IsChecked == truereturn;

 

                //< find record >

                string sSQL = "SELECT [IDDetail] FROM tbl_Details WHERE [dtScan] IS NULL  LIMIT 1";

                SqliteDataReader dataReader = clsDB.Get_DataReader(sSQL);

                //</ find record >

                if (dataReader.HasRows)

                {

                    dataReader.Read();

                    await Scrape_Detail_byIDProjekt(Convert.ToInt32(dataReader["IDDetail"]));

                }

                else

                {

                    fx_Log("no record");

                    break;

                }

            //----</ Detail >----            

            }

 

Richtige Untermethode: mit Task<..>

Der Aufruf der asynchronen Methode funktioniert aber nur, wenn die Methode mit async Task< returnType > definiert wurde.

Andere Definitionen mit async void funktionieren nicht.

Private async Task<bool> Scrape_Detail_byIDProjekt(int ID)

 {

     //--------< Scrape_Detail() >--------

     if (optStop.IsChecked == truereturn false;

 

     //fx_Log("--< Read Detail >--");

     fx_Log("Detail=" + ID);

 

     string sURL = await clsDB.Get_Value_as_String("URL""tbl_Details""[IDDetail]=" + ID);

     HtmlDocument doc = await Web_Get_HtmlDocument(sURL);

     //< check >

     if (doc == null)

     {

         fx_Log("doc is NULL ID" + ID );

         //< update >

         string sql_Error = "UPDATE tbl_Details SET [dtScan] = CURRENT_TIMESTAMP WHERE IDDetail = " + ID;  //SYSDATETIME()

         bool bUpdate = await clsDB.Execute_SQL(sql_Error);

         //</ update >

         return false;

     }

     //</ check >

..

}

Falscher Async / Await  Aufbau

Wenn man den Endlos-Loop aufbaut ohne Await, dann führt es dazu, dass der Debugger immer im Kreis läuft ohne zu warten.

Das heißt, wenn man einen breakpoint auf die Methode oder eine Zeile setzt, dann springt der Debugger bei den Tasten Weiter-Step into-Next (F10,F11,F5) immer wieder auf sich selbst oder den Eintrittspunkt der Methode.

Meistens denkt man dann, die Asynchrone Methode wie sHTML= await httpClient.GetStringAsync(sURL); wäre vom System falsch, doch in wirklichkeit hat man selbst keine Wait funktion eingebaut.

 Falsch:

//----< @Loop: Alle Empty Records >----

while (1 == 1)

{

    //----< Detail >----

    if (optStop.IsChecked == truereturn;

 

    //< find record >

    string sSQL = "SELECT [IDDetail] FROM tbl_Details WHERE [dtScan] IS NULL  LIMIT 1";

    SqliteDataReader dataReader= clsDB.Get_DataReader(sSQL);

    //</ find record >

    if (dataReader.HasRows )

    {

        dataReader.Read();

        Scrape_Detail_byIDProjekt(Convert.ToInt32(dataReader["IDDetail"]));

    }

    else

    {

        break;

    }

    //----</ Detail >----

}

//----</ @Loop: Alle Empty Records >----

 

Und falsche Unter-Methode mit void

Beim Breakpoint auf die unterMethode sHTML= await httpClient.GetStringAsync(sURL); springt der Debugger immer aus der Methode heraus.
Man muss hier dringend darauf achten, dass nicht async void deklariert wird sondern asyn Task<bool>

private async void Scrape_Detail_byIDProjekt(int ID)

        {

            //--------< Scrape_Detail() >--------

            if (optStop.IsChecked == truereturn;

 

            //fx_Log("--< Read Detail >--");

            fx_Log("Detail=" + ID);

 

            string sURL = await clsDB.Get_Value_as_String("URL""tbl_Details""[IDDetail]=" + ID);

            HtmlDocument doc = await Web_Get_HtmlDocument(sURL);

            //< check >

            if (doc == null)

            {

                //< update >

                string sql_Error = "UPDATE tbl_Details SET [dtScan] = CURRENT_TIMESTAMP WHERE IDDetail = " + ID;  //SYSDATETIME()

                bool bUpdate=await clsDB.Execute_SQL(sql_Error);

                //</ update >

                return;

            }

            //</ check >

..

}