Home > Net >  WPF view change is causing lag
WPF view change is causing lag

Time:10-14

I wrote two views in my application, and when I am changin from "Home" to "Details" it causes lag for about 0.5 - 1 sec. I understand, that the reason are my API calls in the constructor, but I added threading, and first filling in an empty properties, and after threads finish it should raise a OnPropertyChange. My "Details" viewmodel is here

public class DetailsViewModel : ObservableObject
{
    private ObservableCollection<Market> _markets;
    private Asset _asset;
    private readonly Uri _baseUri = new Uri("https://cryptingup.com/api/assets/");
    public RestClient Client { get; set; }

    public ObservableCollection<Market> Markets
    {
        get
        {
            return _markets;
        }
        set
        {
            _markets = value;
            OnPropertyChanged();
        }
    }
    public Asset Asset
    {
        get
        {
            return _asset;
        }
        set
        {
            _asset = value;
            OnPropertyChanged();
        }
    }

    public DetailsViewModel(string id)
    {
        Client = new RestClient();
        Markets = new ObservableCollection<Market>();

        new Thread(() =>
        {
            RequestCurrencyDetails(id);
        })
        {
            IsBackground = true
        }.Start();
        RequestAllMarkets(id);

        new Thread(() =>
        {
            RequestAllMarkets(id);
        })
        {
            IsBackground = true
        }.Start();
    }

    private void RequestCurrencyDetails(string id)
    { 
        Uri uri = new Uri(_baseUri, id);
        var request = new RestRequest(uri.ToString());
        request.AddHeader("Accept", "application/json");
        request.AddHeader("Content-Type", "application/json");

        var response = Client.GetAsync(request).GetAwaiter().GetResult();
        var curemodel = JsonConvert.DeserializeObject<CurrencyModelCU>(response.Content);
        Asset = curemodel.Asset;
    }
    private void RequestAllMarkets(string id)
    {
        string marketPath = id   "/markets";
        Uri uri = new Uri(_baseUri, marketPath);

        var request = new RestRequest(uri.ToString());
        request.AddHeader("Accept", "application/json");
        request.AddHeader("Content-Type", "application/json");

        var response = Client.GetAsync(request).GetAwaiter().GetResult();
        var marmodel = JsonConvert.DeserializeObject<MarketsModel>(response.Content);


        ObservableCollection<Market> temp = new ObservableCollection<Market>();
        for (int i = 0; i < 10; i  )
        {
            temp.Add(marmodel.Markets[i]);
        }
        Markets = temp;
    }
}

I know, that I did something wrong with threading here, but I can't get the reason by myself. Thanks for answer

CodePudding user response:

I highly recommend using await async instead of Thread. Also RequestAllMarkets(id); is called synchronously. this is most likley causing the "lag".

Here is a sample how to use Task.Run to "fire and forget the loading operation. https://dotnetfiddle.net/sK3ivq

using System;
using System.Threading;
using System.Diagnostics;
using System.Threading.Tasks;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("start");
        
        Stopwatch sw = new Stopwatch();
        sw.Start();
        DetailsViewModel vm = new DetailsViewModel();
        
        Console.WriteLine($"already back from ctor -> no lag. prove: {sw.ElapsedMilliseconds}ms foo:{vm.Foo}");
        
        // we use thread sleep -> in wpf app you don't have to wait because property change took place in VM.
        Thread.Sleep(1000);
        Console.WriteLine($"we waited long enough...: {sw.ElapsedMilliseconds}ms foo:{vm.Foo}");
    }
    
    public class DetailsViewModel
    {
        public DetailsViewModel()
        {
            Foo= "not initialized";
            Task.Run(()=> Init());
        }
        
        public async Task Init()
        {
            await Task.Delay(500);
            Foo = "bar";
        }
        
        public string Foo {get;set;}
    }
}
  • Related