简体   繁体   English

如何在程序运行时按顺序运行 C# 代码并在视图中显示一些数据

[英]How run C# code in sequence and show some data in view while still program is running

I have a query that I am running in the mvc5.我有一个在 mvc5 中运行的查询。 I need to write the start time on screen, then write something like loading… then write the time that is finished running.我需要在屏幕上写开始时间,然后写一些类似加载……然后写下运行完成的时间。 I am not sure what to use to write this in sequence not all at once, This is my code now that is writing all at once when finished running.我不知道用什么来按顺序写这个,而不是一次,这是我的代码,它在运行完成后立即编写。

   public IActionResult GetQuery()
    {
        ViewData["Timefrom"] = DateTime.Now;
        
        var Query= _context.Order.FromSqlRaw("EXECUTE [dbo].[GetStatusReport].ToList();
        
        ViewData["Timefrom2"] = DateTime.Now;
        
        return View(Query);
    }

and this is my view:这是我的观点:

 @model IEnumerable<Order>
 @{
   ViewData["Title"] = "Home Page";
 }


<tbody>
Start Time: @ViewData["Timefrom"]   //need this showup 1st before query running 
@foreach (var item in Model)        //show loading when here  
{
    <tr>
        <td width="30%">@item.OrderId</td>
        <td width="30%">@item.Name</td>
        <td width="30%">@item.Location</td>
    </tr>
}  
End Time: @ViewData["Timefrom2"]    //show this at end when done running query

Your case is a perfect candidate for a technology called WebSocket.您的案例非常适合称为 WebSocket 的技术。 In Asp.net MVC you can use SignalR library to implement WebSockets with very few lines of code.在 Asp.net MVC 中,您可以使用 SignalR 库以很少的代码行实现 WebSockets。

Update 15/10/2021 : You can follow the example on this answer to know about WebSocket technology and how you can integrate it to your existing Asp.net application. 2021 年 10 月 15 日更新:您可以按照此答案中的示例了解 WebSocket 技术以及如何将其集成到现有的 Asp.net 应用程序中。

For example here is how your page will work:例如,您的页面将如何工作:

  • Page loads from Controller Action.页面从控制器动作加载。 When the page loads you start the heavy process当页面加载时,您开始繁重的过程
  • After the page loads it connects to a specific end point (using WebSocket) on the server.页面加载后,它会连接到服务器上的特定端点(使用 WebSocket)。 Using WebSocket connection the server and page will be able send/receive data as required - Bi-directional!使用 WebSocket 连接,服务器和页面将能够根据需要发送/接收数据 - 双向! In this case server will send updates to the page when required.在这种情况下,服务器将在需要时向页面发送更新。 Page will receive the data.页面将接收数据。 And do not have to pull data with Ajax in intervals.并且不必间隔使用 Ajax 拉取数据。
  • In the bulk process (that you had started when the page was loading) you process data and send an regular update to the WebSocket在批量处理中(您在页面加载时已启动)处理数据并向 WebSocket 发送定期更新
  • Any client connected to the socket will get the data (in this case your page is one client).任何连接到套接字的客户端都将获取数据(在这种情况下,您的页面是一个客户端)。 You can consume the same data from nay different pages.您可以使用来自不同页面的相同数据。

Here is a diagram how the SignalR based WebSocket works (The image is collected from here where you get the detail explanation):这是基于 SignalR 的 WebSocket 的工作原理图(该图像是从此处收集的,您可以在此处获得详细说明):

在此处输入图片说明

Here is a sample Hub:这是一个示例集线器:

using AutoMapper;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Hubs
{
    public class ProcessHub : Hub
    {
        private static IHubContext<ProcessHub> _hubContext;
        public static Dictionary<int, List<KeyValuePair<string, string>>> AppClientStorage = new Dictionary<int, List<KeyValuePair<string, string>>>();

        public ProcessHub(IMapper mapper, IHubContext<ProcessHub> hubContext)
        {
            _hubContext = hubContext;
        }

        public async Task<string> RegisterToSocket(int userId)
        {
            KeyValuePair<string, string> keyValuePair = new KeyValuePair<string, string>(subscriptionTypeName, Context.ConnectionId);

            AddToDictionary(userId, keyValuePair);

            return "Successfully Registered.";
        }

        public static async Task NotifyUpdatesRingAsync(int userId)
        {
            if (AppClientStorage.ContainsKey(userId))
            {
                List<KeyValuePair<string, string>> userSubscriptions = AppClientStorage[userId];

                if (userSubscriptions != null)
                {
                    List<KeyValuePair<string, string>> subscribers = userSubscriptions.ToList();

                    foreach (var subsc in subscribers)
                    {
                        string data = "10% Processed. Please wait..."
                        await _hubContext.Clients.Client(subsc.Value).SendAsync("ReceiveProcessData", data);
                    }
                }
            }
        }

        private void AddToDictionary(int userId, KeyValuePair<string, string> keyValuePair)
        {
            if (!AppClientStorage.ContainsKey(userId))
            {
                AppClientStorage.Add(userId, new List<KeyValuePair<string, string>>() { keyValuePair });
            }
            else
            {
                List<KeyValuePair<string, string>> subscriptions = AppClientStorage[userId];
                List<KeyValuePair<string, string>> connectionList = subscriptions.Where(s => s.Key.Equals(keyValuePair.Key)).ToList();

                if (!connectionList.Any(s => s.Value.Equals(keyValuePair.Value)))
                {
                    subscriptions.Add(keyValuePair);
                    AppClientStorage[userId] = subscriptions;
                }
            }
        }
        
        public override Task OnDisconnectedAsync(Exception exception)
        {
            string connectionId = Context.ConnectionId;
            return base.OnDisconnectedAsync(exception);
        }       
    }
}

Then in the CShtml - Code to connect to the Hub when page loads:然后在 CShtml - 页面加载时连接到集线器的代码:

<script type="text/javascript">

    var connection = new signalR.HubConnectionBuilder()
        .withUrl("/processhub")
        .withAutomaticReconnect()
        .build();

    connection.on("ReceiveProcessData", function (data) {
        // Data sent by the server from the NotifyUpdatesProcessAsync function will arrive here
        // Display the 'Data' on the page as needed
    });

    connection.start();

    function subscribe() {
        connection.invoke("RegisterToSocket", 123).then(function (data) {
            // 123 is ur user Id            
            //Display the data as needed
        }).catch(err => console.error(err.toString()));
    }

</script>

In the Action/Service where you are processing the data, just call the hub method to push the data to the client like this:在处理数据的 Action/Service 中,只需调用 hub 方法将数据推送到客户端,如下所示:

await ProcessHub.NotifyUpdatesProcessAsync(123);

Here 123 is the User Id who will get the data.这里 123 是将获取数据的用户 ID。

If you do not know how to configure a hub and hook it up in startup you can follow any tutorial on the web.如果您不知道如何配置集线器并在启动时将其连接起来,您可以按照网络上的任何教程进行操作。 For example here is one .例如这里是一个.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM