问题描述
这是一篇很长的文章,您可以帮助我为我的问题陈述提供sudo代码/通用的良好编码实践,或者查看我的完整代码(如下)并建议更改。 blazor的新手。
问题陈述:
在我的Blazor Server应用程序中,我有一个显示两个选项卡2020、2021的组件。每个选项卡都从数据库中检索其数据。我模拟了使用Task.Delay进行数据检索的延迟,分别为2秒和3秒。每个标签页(因此2020年将需要2秒加载,而2021年将需要3秒加载) 我的问题是我应该如何设置我的组件,以便在加载数据时显示加载消息,并且一旦有任何一个的数据可用,就向用户显示数据,同时继续为仍然存在的另一个显示加载消息加载中。
我在网上看到了很多建议使用Task.WhenAll的示例,但我想我的情况将需要Task.WhenAny。在这方面也需要更加明确。 标签2020是第一个标签,默认情况下处于打开状态,标签2021是第二个标签,您必须单击它才能打开它。
当前行为:
一旦我进入主页(两个选项卡所在的位置)并等待足够的时间直到加载所有数据(2020年和2021年),然后继续在选项卡之间切换,一切都会按预期进行。但是,如果我登陆主页后很快导航到2021选项卡,则会出现“正在加载数据..”消息(这很好,因为数据仍在加载中),但它永远不会消失。导航到2020选项卡,任务完成后即可看到数据。但是2021年处于“正在加载数据”的永久状态。
这是我的组件标记(Home.razor):
@page "/"
@inherits HomeComponentBase
<RadzenTabs>
<Tabs>
<RadzenTabsItem Text="2020" @onclick="OnTab2020_Click">
@if (MonthlyFinancial_2020 == null)
{
<div>Loading Data..</div>
}
<div>
<canvas id="monthlyExpenseChart_2020"></canvas>
</div>
</RadzenTabsItem>
<RadzenTabsItem Text="2021" @onclick="OnTab2021_Click">
@if (MonthlyFinancial_2021 == null)
{
<div>Loading Data..</div>
}
<div>
<canvas id="monthlyExpenseChart_2021"></canvas>
</div>
</RadzenTabsItem>
</Tabs>
</RadzenTabs>
(HomeComponentBase.cs)后面的代码:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using Newtonsoft.Json;
using RentalPropertyManagement.Models;
using RentalPropertyManagement.Services;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Web;
namespace RentalPropertyManagement.Pages
{
public class HomeComponentBase : ComponentBase
{
public string Title = "4 cedar Ave.";
public IEnumerable<MonthlyFinancial> MonthlyFinancial_2020 { get; set; }
public IEnumerable<MonthlyFinancial> MonthlyFinancial_2021 { get; set; }
[Inject]
public DBService DBService { get; set; }
[Inject]
public IJSRuntime JSRuntime { get; set; }
/*
Use the OnAfterRenderAsync lifecycle method for DB calls as I want to make data available to
ChartJS javascript functions
*/
protected override async Task OnAfterRenderAsync(bool firstRender)
{
Log.information("firstRender: " + firstRender);
if (firstRender)
try
{
var t1 = DBService.GetMonthlyFinancial("2020"); //Start a task to call DB for year 2020 (takes 2 sec to retrieve this data)
var t2 = DBService.GetMonthlyFinancial("2021"); //Start a task to call DB for year 2021 (takes 3 sec to retrieve this data)
var myTasks = new List<Task> { t1,t2 };//Put tasks in a tasks list
while (myTasks.Count > 0) //loop through task list,evicting as they finish.
{
Log.information(firstRender + " About to start tasks");
Task finishedTask = await Task.WhenAny(myTasks); //Await on any task
Log.information(firstRender + " One of the tasks have finished");
if (finishedTask == t1) // t1 complete? Great get its data assign to a variable and call my javascript function
{
MonthlyFinancial_2020 = t1.Result;
Log.information(firstRender + " t1 got data");
StateHasChanged(); //Tell component not to display Loading message any more,but instead show the data for 2020 (I think I may be running into issue due to this as StateHasChanged calls OnAfterRenderAsync again)
await JSRuntime.InvokeVoidAsync("generateMonthlyExpenseChart_2020",JsonConvert.SerializeObject(MonthlyFinancial_2020));
}
else if (finishedTask == t2) // t2 complete? Great get its data assign to a variable and call my javascript function
{
MonthlyFinancial_2021 = t2.Result;
Log.information(firstRender + " t2 got data");
StateHasChanged(); //Tell component not to display Loading message any more,but instead show the data for 2021 (I think I may be running into issue due to this as StateHasChanged calls OnAfterRenderAsync again)
await JSRuntime.InvokeVoidAsync("generateMonthlyExpenseChart_2020",JsonConvert.SerializeObject(MonthlyFinancial_2020));
}
myTasks.Remove(finishedTask); //evict finished tasks
}
}
catch (Exception e)
{
Log.information(e.Message);
}
}
public async Task OnTab2020_Click()
{
if (MonthlyFinancial_2020 != null)
{
await JSRuntime.InvokeVoidAsync("generateMonthlyExpenseChart_2020",JsonConvert.SerializeObject(MonthlyFinancial_2020));
//StateHasChanged();
}
}
public async Task OnTab2021_Click()
{
if (MonthlyFinancial_2021 != null)
{
await JSRuntime.InvokeVoidAsync("generateMonthlyExpenseChart_2021",JsonConvert.SerializeObject(MonthlyFinancial_2021));
//StateHasChanged();
}
}
}
}
数据库服务类。注意Task.Delay以模拟延迟。 (DBService.cs):
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using RentalPropertyManagement.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.sqlClient;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Serilog;
using System.Threading;
namespace RentalPropertyManagement.Services
{
public class DBService
{
private string connString = @"Server=****";
private string qryToOpen;
private StreamReader file;
private string sql;
public IDbConnection Connection
{
get
{
return new sqlConnection(connString);
}
}
public async Task<IEnumerable<MonthlyFinancial>> GetMonthlyFinancial(string year)
{
qryToOpen = "GetMonthlyFinancial.sql";
file = new StreamReader(Constants.CURRDIR_Queries + qryToOpen);
sql = file.ReadToEnd();
file.Close();
var parameter = new { Year = year };
try
{
using (IDbConnection dbConnection = Connection)
{
dbConnection.open();
Log.information("Parameter:\n" + "@Year:" + parameter.Year);
Log.information("Query: " + sql);
if(year.Equals("2020"))
await Task.Delay(2000);
if(year.Equals("2021"))
await Task.Delay(3000);
return await dbConnection.QueryAsync<MonthlyFinancial>(sql,parameter);
}
}
catch (Exception e)
{
Log.information("Exception cccurred while retriving data from database\n" + "Exception detail: " + e.Message);
return null;
}
}
}
}
模型(MonthlyFinancial.cs):
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RentalPropertyManagement.Models
{
public class MonthlyFinancial
{
public int Year { get; set; }
public string Month { get; set; }
public float Expenditure { get; set; }
public float Income { get; set; }
public float Net { get; set; }
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)