[.Net] Async await probleem

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 17:19
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


Acties:
  • +1 Henk 'm!

  • 1superheld
  • Registratie: September 2011
  • Laatst online: 01-06 15:30
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 ]


Acties:
  • +2 Henk 'm!

  • 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
}

Acties:
  • 0 Henk 'm!

  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 17:19
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


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 19:47

Sebazzz

3dp

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]


Acties:
  • 0 Henk 'm!

  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 17:19
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


Acties:
  • 0 Henk 'm!

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

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • doskabouter
  • Registratie: Oktober 2004
  • Laatst online: 17:19
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


Acties:
  • 0 Henk 'm!

  • W99
  • Registratie: September 2015
  • Laatst online: 21-05 14:01

W99

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

Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 19:47

Sebazzz

3dp

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]


Acties:
  • 0 Henk 'm!

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

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

Pagina: 1