1

Im creating a list of components in Blazor, each one of these components need to request some data from a webpage. The list are created as follows on a .razor page:

@foreach(stringcomp in Complist){
   <myComponent />
}

around 100 components are created. On all of these components the following URL request is preformed (using this code):

        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                await GetUrl("some url here");
            }
        }


        public async Task<string> GetUrl(string url)
        {
            HttpClient client = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Get, url);
            request.Headers.Add("User-Agent", "get data service");
            var response = await client.SendAsync(request).ConfigureAwait(false);
            string res = null;
            if (response.IsSuccessStatusCode)
            {
                using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
                var streamReader = new StreamReader(responseStream);
                res = await streamReader.ReadToEndAsync().ConfigureAwait(false);
            }
            return res;
        }

Doing this I'm running in to some problems where most of my calls to SendAsync never returns a value. I have come to understand that this is because of a lock-state but for the life of me can't figure out how to solve it. most similar answers suggest setting .ConfigureAwait(false) but this does not yeald a different result in my case.

So my question is: Hos can i request webbpages simultaneously in different components and be sure that they won't hang/lookup. As theres many requests that some times takes a long time (5-10 sec) to complete it's not an alternative to do them synchronously.

It might also be of importance to mention that me code and pages are separated, every .razor page are using @inherits to get its functions/logic

3
  • Is there a reason why you make a request per <myComponent> and not a single http request getting all data you need to display ? Commented Jun 12, 2020 at 13:04
  • in total there's over 500 requests, some are slow to get an answer from, if i need to wait for my data before i display it the waiting time can get very long. An alternative would be to do everything in the parent and pass the data to the childs as it is received, but why would this be needed? I can't see why my approach aren't working as doing separate requests in different components should work fine (even if my case are some what extreme) Commented Jun 12, 2020 at 13:27
  • A browser is generally limited to 5 parallels requests (2 on mobile) and Blazor is not yet really multithreaded, That could explains your issue Commented Jun 12, 2020 at 14:15

1 Answer 1

1

Try to use IHttpClientFactory as follows:

[Inject] public IHttpClientFactory clientFactory { get; set;}
using System.IO;

Your GetUrl method:

 public async Task<string> GetUrl(string url)
{
    var request = new HttpRequestMessage(HttpMethod.Get, url);
    request.Headers.Add("Accept", "application/json");
    request.Headers.Add("User-Agent", "get data service");


    var client = clientFactory.CreateClient();

    var response = await client.SendAsync(request);

    string res = null;

    if (response.IsSuccessStatusCode)
    {
        using var responseStream = await response.Content.ReadAsStreamAsync();
        var streamReader = new StreamReader(responseStream);
        res = await streamReader.ReadToEndAsync().ConfigureAwait(false);
    }

    return res;
}

Startup.cs

 public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient();

    // More code here...
 }

Hope this works...

Sign up to request clarification or add additional context in comments.

9 Comments

@inject IHttpClientFactory clientFactory is only for .razor pages but my code resign inside inside of a .cs. my .razor page inherits the .cs.
Add this property into your class behind: [Inject] public IHttpClientFactory clientFactory { get; set;}
tried your code and unfortunately the problem still persists, some of the SendAsync calls never returns (probably dead lock)
What are you trying to do ? Why do you have to instantiate 100 component and store them in a list ?
each component represent a different webpage, every component are suppose to fetch information about its own page (this is why every component has its own requests) and display it. Problem is that only a few of the SendAsync calls do return, most of them get stuck and never return anything.NOTE: as the list items are created in a loop, all requests are sent away almost at the same time.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.