Blazor用户界面锁定 [英] Blazor UI locking

查看:32
本文介绍了Blazor用户界面锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:它是从json到锁定线程的类的转换。我用一个较小的数据包尝试了同样的过程,但用户界面并没有冻结。所以问题是如何克服这一点?

我正在尝试从JSON获取一个被解析为类的值:

 public async Task<BitcoinDetails> GetData()
    {

        return await _httpClient.GetFromJsonAsync<BitcoinDetails>("https://localhost:5001/proxy");

    }

我使用OnInitializedAsync将数据加载到视图中,但是以下代码锁定了UI

_bitcoinDetails = new BitcoinDetails();
        _bitcoinDetails = await _bitcoinApiService.GetData();

        var price = _bitcoinDetails.data.Find(x => x.symbol == "BTC");
        if (price == null)
        {
            _bitcoinPrice = 0;
        }

        _bitcoinPrice = double.Parse(price.quote.USD.price.ToString());

如何重构此代码以在不锁定UI的情况下加载数据?

查看代码:

 @if (_bitcoinDetails == null)
{
    <p><em>Loading...</em></p>
}
else
{
<h3>BTC:@_bitcoinPrice</h3>
}

推荐答案

Blazor WebAssembly中的多线程

Blazor WebAssembly还没有真正的多线程支持。所有任务有效地运行在与用户界面相同的线程上,这意味着任何CPU密集型工作的执行时间超过几毫秒都可能导致用户界面明显冻结。

不幸的是,在.NET6(2021年11月)之前,Blazor WebAssembly中的多线程情况不太可能得到改善。在此之前,解决方法是在CPU密集型任务流中手动引入短暂停顿,以便用户界面可以在这些间歇期间控制并执行其工作:

async Task PerformCpuIntensiveWorkAsync()
{
    for (int i = 0; i < 100; i++)
    {
        PerformOneHundredthOfWork();
        await Task.Delay(1);
    }
}

大型JSON的反序列化

大多数JSON序列化程序提供低级API,使您可以完全控制反序列化过程:

如果您需要反序列化一个大型JSON,例如,包含100,000辆汽车的数组

[
  { "make": "Ford", "model": "Mustang", "year": 2000 },
  { "make": "Honda", "model": "Civic", "year": 2005 },
  { "make": "Chevrolet", "model": "Corvette", "year": 2008 },
  ...
]

https://api.npoint.io/d159a22063995b37c52d

下载此JSON

以下是使用JSON.Net在反序列化过程中引入短中断的方法:

using Newtonsoft.Json;
using System.IO;

...

public class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
}

...

using var jsonStream = await Http.GetStreamAsync("https://api.npoint.io/d159a22063995b37c52d");

List<Car> cars = await DeserializeCarsAsync(jsonStream);

static async Task<List<Car>> DeserializeCarsAsync(Stream jsonStream)
{
    using var streamReader = new StreamReader(jsonStream);
    using var jsonReader = new JsonTextReader(streamReader);
    var serializer = new JsonSerializer();

    if (!jsonReader.Read())
        throw new JsonException($"Deserialization failed at line {jsonReader.LineNumber} position {jsonReader.LinePosition}.");
    if (jsonReader.TokenType != JsonToken.StartArray)
        throw new JsonException($"Deserialization failed at line {jsonReader.LineNumber} position {jsonReader.LinePosition}.");

    List<Car> cars = new List<Car>();
    while (true)
    {
        if (!jsonReader.Read())
            throw new JsonException($"Deserialization failed at line {jsonReader.LineNumber} position {jsonReader.LinePosition}.");
        if (jsonReader.TokenType == JsonToken.EndArray)
            return cars;
        if (jsonReader.TokenType != JsonToken.StartObject)
            throw new JsonException($"Deserialization failed at line {jsonReader.LineNumber} position {jsonReader.LinePosition}.");

        var car = serializer.Deserialize<Car>(jsonReader);
        cars.Add(car);

        // Pause after every 10th deserialized car:

        if (cars.Count % 10 == 0)
            await Task.Delay(1);
    }
}

如果您必须处理嵌套集合,它看起来确实过于复杂,甚至会变得更糟,但它解决了问题。

其他选项

  • 如果可能,请使用较小的JSON。看起来您正在使用代理从CoinMarketCap获取报价或列表。您得到了整个列表,但只需要一项-BTC。在不知道详细信息的情况下很难说这是否适合您,但可以要求CoinMarketCap服务器为您过滤结果并只返回BTC报价的数据-这将导致JSON:https://sandbox-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?CMC_PRO_API_KEY=b54bcf4d-1bca-4e8e-9a24-22ff2c3d462c&symbol=BTC小得多。

  • 尝试更快的JSON序列化程序。Utf8Jsonlooks promising

  • 如果只需要反序列化大型JSON中的几个字段,则有许多潜在的优化方法:

    • 尝试反序列化为具有较少字段的类。例如,如果您反序列化Quote对象并且只需要获取它们的价格,请尝试使用具有唯一属性Price的类来反序列化为:class Quote { decimal Price {get; set;} }
    • 尝试使用JsonDocument只反序列化您需要的特定JSON节点。不过,它仍然需要首先解析整个JSON以创建其节点的映射,但无论如何,它应该比反序列化整个JSON更快。
    • 如果您使用的是序列化程序的底层API,它们中的大多数允许在解析时跳过JSON元素(JsonReader.SkipUtf8JsonReader.SkipJsonReader.ReadNextBlock等)。

这篇关于Blazor用户界面锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆