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