Toon posts:

[.Net] Async await probleem

Pagina: 1
Acties:

Vraag


  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 31-03 17:07
Hoi,

Ik ben al een paar dagen aan het experimenteren met de webview2 component in .NET
Meeste dingen lukken al aardig maar loop nu al een tijdje stuk op het opvragen van de html uit de DOM.
Er is nog geen native property in de webview component maar met een simpele js functie (document.documentElement.outerHTML) is deze wel opvraagbaar.

Probleem hiermee is dat de enige method om js uit te voeren in een webview component een async functie is, en de verschillende manieren om te wachten op het resultaat leveren of een infinite loop, of zelfs een program crash (zonder exception in de debugger...) op.

relevante code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        private void Form1_Load(object sender, EventArgs e)
        {
            webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
            webView.Source = new Uri("https://npostart.nl/");
        }

        private void WebView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
        {
            if (!e.IsSuccess)
                throw new Exception("init error");
            webView.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded;
        }

        private void CoreWebView2_DOMContentLoaded(object sender, Microsoft.Web.WebView2.Core.CoreWebView2DOMContentLoadedEventArgs e)
        {
            string html=GetDoc().Result;
            //do something
        }
        private async Task<String> GetDoc()
        {
            return await webView.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML");
        }

in dit geval komt ie nooit bij de //dosomething.
zelfs dit halfbakken experiment:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        private string hh = null;
        private void CoreWebView2_DOMContentLoaded(object sender, Microsoft.Web.WebView2.Core.CoreWebView2DOMContentLoadedEventArgs e)
        {
            GetDoc();
            do
            {
                Application.DoEvents();
            }
            while (hh == null);
            //do something
        }
        private async void GetDoc()
        {
            string html = await webView.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML");
            hh = html;
        }

Wil de hh niet vullen
Ook diverse Task.wait et al experimentjes leverden niks op

Wat is de goede manier om te wachten op zo'n async functie? En nee, ik kan niet het hele spul async maken..

Het grote voordeel van windows is dat je meer dos-boxen kan openen

Alle reacties


  • 1superheld
  • Registratie: September 2011
  • Laatst online: 14:55
Beste is wel alles async maken, maar ik verwacht dat een thread gedeadlocked wordt (.Result op een task die niet completed is, kan dat doen).

Als je perse een async functie sync wil aanroepen is dit een goede helper methode. (zal je wel als utility in je eigen code moeten opnemen)
https://github.com/aspnet...ntity.Core/AsyncHelper.cs

Maar waarom kan de event handler niet async void worden? (let op: try catch async void altijd)

[Voor 15% gewijzigd door 1superheld op 01-01-2022 14:59]


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Je kan wel je event-handler async maken. In je eerste voorbeeld met de "async Task<String> GetDoc()" wordt het dan:
C#:
1
2
3
4
5
private async void CoreWebView2_DOMContentLoaded(object sender, Microsoft.Web.WebView2.Core.CoreWebView2DOMContentLoadedEventArgs e)
{
    string html = await GetDoc();
    //do something
}

  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 31-03 17:07
Alles async gaat hem niet worden, dit moet nl onderdeel worden van een bestaand programma en om dat helemaal async te gaan maken is niet te doen (groot, veel etc).

Ook even gekeken naar die AsyncHelper, maar die maakt een nieuwe thread aan waar die het werk gaat doen. Helaas alleen is dat de CoewWebView2 alleen door de UI thread gebruikt mag worden, dus dat lijkt ook weer een dead-end...

Alternatief is moglijk dat ik voor alle async spullen die ik nodig heb een callback ga doen waar dan de volgende stappen in moeten gebeuren, maar dat word (vrees ik bij meerdere stappen) toch snel een onoverzichtelijke bende...

Het grote voordeel van windows is dat je meer dos-boxen kan openen


  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 12:56
Probeer eens `ExecuteScriptAsync(..).ConfigureAwait(false)`. Je hebt namelijk op dit moment het probleem dat de continuation van de task van `ExecuteScriptAsync` zit te wachten op de UI thread, terwijl de UI thread geblokt zit op het resultaat van die task.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 31-03 17:07
Sebazzz schreef op zaterdag 1 januari 2022 @ 16:50:
Probeer eens `ExecuteScriptAsync(..).ConfigureAwait(false)`. Je hebt namelijk op dit moment het probleem dat de continuation van de task van `ExecuteScriptAsync` zit te wachten op de UI thread, terwijl de UI thread geblokt zit op het resultaat van die task.
Kan je me effe iets meer in de richting duwen?
toevoegen van de .ConfigureAwait in de async method geeft me nog steeds een hangende app als ik de GetDoc().Result wil hebben.

Het grote voordeel van windows is dat je meer dos-boxen kan openen


  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Gebruikt het misschien de shadowDOM?

Maak je niet druk, dat doet de compressor maar


  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 31-03 17:07
Intussen min of meer een manier gevonden (niet de netste maar het werkt iig)

in de CoreWebView2_DOMContentLoaded een nieuwe thread starten die
string html=doc() aanroept en van daaruit verder gaat

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
        private void WaitForTaskCompleted(Task t)
        {
            do
            {
                System.Windows.Forms.Application.DoEvents();
            }
            while (!t.IsCompleted);
        }

        private string doc()
        {
            var rr = getDoc();
            WaitForTaskCompleted(rr);
            return rr.Result;
        }

        private async Task<String> getDoc()
        {
            string html = null;
            try
            {
                html = await webView.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML");
            }
            catch
            {
            }

            return html;
        }

Het grote voordeel van windows is dat je meer dos-boxen kan openen


  • W99
  • Registratie: September 2015
  • Laatst online: 30-03 13:40
Hier wat documentatie wat volgens mij met je probleem te maken heeft: https://docs.microsoft.co.../concepts/threading-model Voornamelijk het stukje Block the UI thread

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 12:56
Ja, dit lijkt dus de uitzondering te zijn waarbij je wel een async void mag gebruiken als event handler.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 31-03 17:07
Dank, interessant leesvoer weer. Hier ga ik eens induiken

Het grote voordeel van windows is dat je meer dos-boxen kan openen

Pagina: 1


Tweakers maakt gebruik van cookies

Tweakers plaatst functionele en analytische cookies voor het functioneren van de website en het verbeteren van de website-ervaring. Deze cookies zijn noodzakelijk. Om op Tweakers relevantere advertenties te tonen en om ingesloten content van derden te tonen (bijvoorbeeld video's), vragen we je toestemming. Via ingesloten content kunnen derde partijen diensten leveren en verbeteren, bezoekersstatistieken bijhouden, gepersonaliseerde content tonen, gerichte advertenties tonen en gebruikersprofielen opbouwen. Hiervoor worden apparaatgegevens, IP-adres, geolocatie en surfgedrag vastgelegd.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Toestemming beheren

Hieronder kun je per doeleinde of partij toestemming geven of intrekken. Meer informatie vind je in ons cookiebeleid.

Functioneel en analytisch

Deze cookies zijn noodzakelijk voor het functioneren van de website en het verbeteren van de website-ervaring. Klik op het informatie-icoon voor meer informatie. Meer details

janee

    Relevantere advertenties

    Dit beperkt het aantal keer dat dezelfde advertentie getoond wordt (frequency capping) en maakt het mogelijk om binnen Tweakers contextuele advertenties te tonen op basis van pagina's die je hebt bezocht. Meer details

    Tweakers genereert een willekeurige unieke code als identifier. Deze data wordt niet gedeeld met adverteerders of andere derde partijen en je kunt niet buiten Tweakers gevolgd worden. Indien je bent ingelogd, wordt deze identifier gekoppeld aan je account. Indien je niet bent ingelogd, wordt deze identifier gekoppeld aan je sessie die maximaal 4 maanden actief blijft. Je kunt deze toestemming te allen tijde intrekken.

    Ingesloten content van derden

    Deze cookies kunnen door derde partijen geplaatst worden via ingesloten content. Klik op het informatie-icoon voor meer informatie over de verwerkingsdoeleinden. Meer details

    janee