如何防止Blazor服务器端页面冻结?

如何防止Blazor服务器端页面冻结?,blazor,Blazor,我有一组与gRPC服务器通信的应用程序。这些应用程序运行在Blazor服务器端,一切都很好,几乎!!! 它应该像本地聊天一样工作。我在一台机器上写一个东西,所有其他机器都会收到并显示它。为了显示它,我有一个计时器检查应用程序自己的gRPC服务是否接收到任何东西,我将数据抓取到页面变量中,并调用状态已更改。 问题是页面在一段时间后冻结。当没有人在他们身上工作时,这种情况就会发生。 我没有发现任何错误。谁能帮帮我吗 第页中的代码: @code { bool registred = false

我有一组与gRPC服务器通信的应用程序。这些应用程序运行在Blazor服务器端,一切都很好,几乎!!! 它应该像本地聊天一样工作。我在一台机器上写一个东西,所有其他机器都会收到并显示它。为了显示它,我有一个计时器检查应用程序自己的gRPC服务是否接收到任何东西,我将数据抓取到页面变量中,并调用状态已更改。 问题是页面在一段时间后冻结。当没有人在他们身上工作时,这种情况就会发生。 我没有发现任何错误。谁能帮帮我吗

第页中的代码:

@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");
            });
        }
    }
}