如何防止Blazor服务器端页面冻结?
我有一组与gRPC服务器通信的应用程序。这些应用程序运行在Blazor服务器端,一切都很好,几乎!!! 它应该像本地聊天一样工作。我在一台机器上写一个东西,所有其他机器都会收到并显示它。为了显示它,我有一个计时器检查应用程序自己的gRPC服务是否接收到任何东西,我将数据抓取到页面变量中,并调用状态已更改。 问题是页面在一段时间后冻结。当没有人在他们身上工作时,这种情况就会发生。 我没有发现任何错误。谁能帮帮我吗 第页中的代码:如何防止Blazor服务器端页面冻结?,blazor,Blazor,我有一组与gRPC服务器通信的应用程序。这些应用程序运行在Blazor服务器端,一切都很好,几乎!!! 它应该像本地聊天一样工作。我在一台机器上写一个东西,所有其他机器都会收到并显示它。为了显示它,我有一个计时器检查应用程序自己的gRPC服务是否接收到任何东西,我将数据抓取到页面变量中,并调用状态已更改。 问题是页面在一段时间后冻结。当没有人在他们身上工作时,这种情况就会发生。 我没有发现任何错误。谁能帮帮我吗 第页中的代码: @code { bool registred = false
@code {
bool registred = false;
int countLogingAttempts = 2;
string Name = "first name";
public string displayLoader = "block";
public string displayQueuesContainer = "none";
private string Time { get; set; }
public System.Threading.Timer LoginTimer { get; set; }
public string[] queueNames = new string[0];
public int[] queueNumbers = new int[0];
public int countStateChanged = 0;
string selectedQueueName = "";
string SelectedQueueName
{
get => selectedQueueName;
set
{
selectedQueueName = value;
}
}
public bool[] displayQueues = new bool[4] { false, false, false, false };
protected override void OnInitialized()
{
jsRuntime.InvokeAsync<string>("console.log", "intilializing " + countLogingAttempts);
LoginTimer = new System.Threading.Timer((_) =>
{
jsRuntime.InvokeAsync<string>("console.log", "Tiking");
if (!registred)
{
int capturedint = countLogingAttempts;
jsRuntime.InvokeAsync<string>("console.log", "Trying " + capturedint);
if (countLogingAttempts == 5)
{
Task.Run(() => SayHello());
countLogingAttempts = 0;
jsRuntime.InvokeAsync<string>("console.log", "Say hello ");
}
countLogingAttempts += 1;
}
else
{
displayLoader = "none";
displayQueuesContainer = "block";
InvokeAsync(StateHasChanged);
updatePage();
jsRuntime.InvokeAsync<string>("console.log", "Disposed" + countLogingAttempts);
LoginTimer.Dispose();
}
}, null, 0, 1000);
}
public void updatePage()
{
var timer = new System.Threading.Timer((_) =>
{
if (registred)
{
Time = DateTime.Now.ToString("HH:mm");
jsRuntime.InvokeAsync<string>("console.log", "Registred." + countLogingAttempts);
queueNames = GreeterService1.queueNames;
queueNumbers = GreeterService1.queueNumbers;
InvokeAsync(StateHasChanged);
}
}, null, 0, 1000);
}
async Task SayHello()
{
this.registred = await this.GreeterService1.SayHello(this.Name);
await jsRuntime.InvokeAsync<string>("console.log", "waiting for hello " + registred);
}
@code{
bool registed=false;
int countLogingAttempts=2;
string Name=“first Name”;
公共字符串displayLoader=“block”;
公共字符串displayQueuesContainer=“无”;
私有字符串时间{get;set;}
public System.Threading.Timer LoginTimer{get;set;}
公共字符串[]队列名称=新字符串[0];
public int[]queueNumbers=新int[0];
公共int countStateChanged=0;
字符串selectedQueueName=“”;
字符串SelectedQueueName
{
get=>selectedQueueName;
设置
{
selectedQueueName=值;
}
}
public bool[]displayQueues=new bool[4]{false,false,false,false};
受保护的覆盖无效OnInitialized()
{
jsRuntime.InvokeAsync(“console.log”,“初始化”+countLogingAttempts);
LoginTimer=新系统.线程.计时器(()=>
{
jsRuntime.InvokeAsync(“console.log”、“Tiking”);
如果(!已注册)
{
int capturedint=countLogingAttempts;
jsRuntime.InvokeAsync(“console.log”,“Trying”+capturedint);
如果(countLogingAttempts==5)
{
Task.Run(()=>SayHello());
countLogingAttempts=0;
jsRuntime.InvokeAsync(“console.log”,“说你好”);
}
countLogingAttempts+=1;
}
其他的
{
displayLoader=“无”;
displayQueuesContainer=“block”;
InvokeAsync(statehaschange);
updatePage();
jsRuntime.InvokeAsync(“console.log”,“Disposed”+countLogingAttempts);
LoginTimer.Dispose();
}
},空,0,1000);
}
公共无效更新页()
{
var timer=新系统.线程.计时器(()=>
{
如果(已注册)
{
Time=DateTime.Now.ToString(“HH:mm”);
jsRuntime.InvokeAsync(“console.log”、“registed.”+countLogingAttempts);
queueNames=GreeterService1.queueNames;
QueueNumber=GreeterService1.QueueNumber;
InvokeAsync(statehaschange);
}
},空,0,1000);
}
异步任务SayHello()
{
this.registed=等待this.GreeterService1.SayHello(this.Name);
wait jsRuntime.InvokeAsync(“console.log”,“waiting for hello”+registed);
}
一些标记:
<div class="col col-sm-auto col-clock">
<div style="margin-right:0px;width: 125px;">
<h5 id="clock">@Time</h5>
</div>
</div>
<div class="container-fluid main-container">
<div class="row main-row">
<div id="queueContainer" class="col col-md-auto senhas-col">
@if (queueNames!=null) {
if (queueNames.Length>0) {
<div class="row senhas-row">
<div class="queue-name-div">
<a class="queue-name-a ">@queueNames[0]</a>
@时间
@if(queueNames!=null){
如果(queueNames.Length>0){
@队列名称[0]
gRPC服务:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
using Microsoft.Extensions.Logging;
using GrpcConsole;
using BlazorViewer;
using BlazorViewer.Data;
namespace GrpcService1
{
public class GreeterService : QueueManagement.QueueManagementBase
{
public static string clientName="Initial name";
public string[] queueNames;
public int[] queueNumbers;
public static string calledQueue { get; set; }
public static string publicAuthToken = "token";
public static bool serviceStatus = false;
public static string token = "token";
public static string guidId = "viewer1";
public static string kind = "viewer";
public static int numberInKind = 1;
public static string serverIp = "192.168.5.56";
public async Task<bool> SayHello(string name)
{
bool awnser = false;
Task t = Task.Run(async () => {
var httpClientHandler = new HttpClientHandler();
// Return `true` to allow certificates that are untrusted/invalid
httpClientHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(httpClientHandler);
var channel = GrpcChannel.ForAddress("https://"+serverIp+":5001"
, new GrpcChannelOptions { HttpClient = httpClient });
var client = new QueueManagement.QueueManagementClient(channel);
IdMessage message = new IdMessage { Token = token, GuidId = guidId, Kind = kind, NumberInKind = numberInKind };
var request = await client.GeneralRegistryRequestAsync(new RegistryRequest { Identification = message });
awnser = request.RequestAccepted;
});
t.Wait();
Console.WriteLine("Registry made = "+ awnser);
return await Task.FromResult(awnser);
}
public static void ProcessServiceStatus(bool status)
{
serviceStatus = status ? true : false;
}
public override async Task<RequestResponse> UpdateToViewer(ViewerUpdate request, ServerCallContext context)
{
RequestResponse resp = new RequestResponse { RequestAccepted = false };
if (request.Token == publicAuthToken)
{
resp.RequestAccepted = true;
ProcessServiceStatus(request.ServiceStatus);
string[] queueNames1 = request.QueueNames.ToArray();
int[] queueNumbers1 = request.QueueNumbers.ToArray();
queueNames = new string[queueNames1.Length];
queueNumbers = new int[queueNames1.Length];
queueNames = queueNames1;
queueNumbers = queueNumbers1;
Console.WriteLine("Received queues:");
foreach (var item in queueNames)
{
Console.WriteLine(item);
}
}
return await Task.FromResult(resp);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Net.Http;
使用系统线程;
使用System.Threading.Tasks;
使用Grpc.Core;
使用Grpc.Net.Client;
使用Microsoft.Extensions.Logging;
使用GrpcConsole;
使用BlazorViewer;
使用BlazorViewer.Data;
命名空间GrpcService1
{
公共类GreeterService:QueueManagement.QueueManagementBase
{
公共静态字符串clientName=“初始名称”;
公共字符串[]队列名称;
公共整数;
被调用的公共静态字符串队列{get;set;}
公共静态字符串publicAuthToken=“token”;
公共静态布尔服务状态=false;
公共静态字符串token=“token”;
公共静态字符串guidId=“viewer1”;
公共静态字符串kind=“viewer”;
公共静态int numberInKind=1;
公共静态字符串serverIp=“192.168.5.56”;
公共异步任务SayHello(字符串名称)
{
bool-awnser=false;
Task t=Task.Run(异步()=>{
var httpClientHandler=新的httpClientHandler();
//返回'true'以允许不受信任/无效的证书
httpClientHandler.ServerCertificateCustomValidationCallback=
HttpClientHandler.DangerousAcceptionServerCertificateValidator;
var httpClient=新的httpClient(httpClientHandler);
var channel=GrpcChannel.ForAddress(“https://“+serverIp+”:5001”
,新的GRPCChannel选项{HttpClient=HttpClient});
var client=new QueueManagement.QueueManagementClient(通道);
IdMessage message=newIDMessage{Token=Token,GuidId=GuidId,Kind=Kind,NumberInKind=NumberInKind};
var request=wait client.GeneralRegistryRequestAsync(新的RegistryRequest{Identification=message});
awnser=request.RequestAccepted;
});
t、 等待();
Console.WriteLine(“注册表生成=”+awnser);
返回等待任务。FromResult(awnser);
}
公共静态无效ProcessServiceStatus(bool状态)
{
serviceStatus=状态?真:假;
}
公共覆盖异步任务UpdateToViewer(ViewerUpdate请求,ServerCallContext上下文)
{
RequestResponse resp=newrequestresponse{RequestAccepted=false};
如果(request.Token==publicAuthTok
namespace BlazorViewer
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<GreeterService>();
services.AddGrpc();
services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; });
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}