ASP.net Web 表单应用程序中的实时数据:如何使用新传入数据更新(刷新)屏幕
Real Time Data in ASP.net Web Form App : How to update (refresh) screen with new incoming data
我知道有很多关于这个特定主题的问题,但我找不到适合我情况的问题。
我的测试应用程序是使用 ASP.Net Web 表单构建的。我使用的库是与 .Net Core 不兼容的 .Net 库,因此我仅限于 .net Framework。
我正在使用提供连接和数据处理的第三方库从 PLC 服务器(使用 TCP/IP 的 Modbus 协议)检索数据,处理程序...我不需要实施“模型”或“控制器”,因为一切都在 类 内处理。这是一个例子:
//References
using AutomatedSolutions.Win.Comm;
using MB = AutomatedSolutions.Win.Comm.MB.Master;
using System;
using System.Text;
using System.Web.UI.WebControls;
protected void Page_Load(object sender, EventArgs e)
{
//Properties Instantiation
mbChannel = new MB.Net.Channel(); //Connection to the server TCP/IP
device1 = new MB.Device(); //Device sending data (temp, speed, ...)
group1 = new MB.Group(false, 500); //Abstract class with a "dataChanged event"
item1 = new MB.Item(); //Represents a specific data point (tag)
group1.Items.Add(item1);
mbChannel.Devices.Add(device1);
device1.Groups.Add(group1);
//Data changed Event Handler
item1.DataChanged += new Item.DataChangedEventHandler(Item_DataChanged);
//Polling activation
group1.Active = true;
}
连接到服务器后,“Item.DataChangedEventHandler”每 500 毫秒触发一次,可以从“项目”中检索新数据。
"Item.DataChangedEventHandler" 代码:
private void Item_DataChanged(object sender, EventArgs evArgs)
{
Item evItem = (Item)sender;
TextBox1.Text = TextBox1.Text + DateTime.Now.ToString("hh:mm:ss:fff") + " Item.DataChange event fired, quality is " + evItem.Quality.ToString();
if (evItem.Quality == AutomatedSolutions.Win.Comm.Quality.GOOD)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < evItem.Elements; i++)
{
sb.Append(evItem.Values[i].ToString() + ",");
}
WriteResult(sb.ToString());
}
}
WriteResults代码:
private void WriteResult(string result)
{
Result.Text = result;
}
DoRead 代码:此函数由按钮动作触发,一次读取一项。这工作正常,读取值显示在“文本框”
private void DoRead(TextBox tb)
{
Result result;
try
{
device1.Read(item1, out result);
if (result.IsOK)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < item1.Elements; i++)
{
sb.Append(item1.Values[i].ToString() + ",");
sb.Length = sb.Length - 1;
tb.Text = sb.ToString();
TextBox1.Text = "Success";
}
}
else
{
TextBox1.Text = TextBox1.Text + result.EvArgs.Message;
}
}
catch (Exception ex)
{
TextBox1.Text = TextBox1.Text + ex.Message;
}
}
我的问题是,虽然使用“DoRead”方法读取项目的值工作正常,但未显示从“dataChanged”事件收集的数据。未触发 TextChanged 事件。
如何使用传入数据更新页面?
嗯,如上所述,您需要掌握 Web 表单或页面的生命周期。
后面的代码只存在于我们所说的往返过程中。
于是,用户请求了一个网页。页面 class 和变量等已创建。 运行s后面的代码,页面发送到客户端。
然后服务器端页面被丢弃 - 不再存在
(现在一遍又一遍地阅读它!!-服务器端代码、变量和页面被丢弃了-它不存在!!!)。
你必须毫无疑问地掌握以上概念。
所以,网页现在被发送到客户端,浏览器重新绘制该页面。它只是坐在用户桌面上,服务器页面 code/page/variable 等现在已经消失了!!!!
最终用户可以拔下他们计算机的插头,也许可以走捷径并转到 google.com。该页面已与网络服务器断开连接!
它从未连接过。该网页就位于用户桌面上。背后的代码早已消失 - 不再存在!!!
Web 服务器因此就坐在那里。它正在等待任何用户的 post-返回。它不会在内存中保存或保留您的网页和代码的副本。 Web 服务器可以接受任何网页请求。
因此,您不能在此过程中运行在网页中保留某些代码。
如果桌面上有网页的 10 个用户中有任何一个点击了按钮?然后,如果发生 post-back,则整个网页将发送到等待该请求的一个 Web 服务器。
然后重新加载页面。页面 class 和变量被重新初始化(从头开始)。现在后面的代码 运行s。您可以更改网页上的内容,只有当所有代码都完成后 运行ning 才会将页面发送回浏览器,然后浏览器会再次重新加载整个页面。
我的意思是,如果该页面有 10 个用户 post 会怎样?您现在拥有该代码和页面的 10 个副本 运行ning!!!!哪个将连接到外部进程??
你有这个设置:
注意页面是如何位于客户端的。在服务器上,没有该页面的实例 class。 (再读一遍这句话!!!)
注意这里非常小心 - 网页在客户端计算机上 - 它根本不存在于网络服务器端。
你没有这个:
你也没有这个:
上面是用户桌面上的网页,然后是服务器上的网页。
你没有那个设置。
页面服务器端不存在。
所以,你有一个网页,你点击了一个按钮:
好的,您点击按钮。现在开始所谓的往返。
所以你点击一个按钮整个网页就是
发送到服务器。你现在有这个:
现在在上面,我想图表可以显示网页也仍然是客户端。但是我把它漏掉了。
现在页面 class 的一个实例已创建,您的后台代码开始 运行ning。
您的隐藏代码可以修改控件(甚至可见),但页面不与用户交互 - 只有代码可以修改网页。
然后将网页发送回客户端,服务器端 class 实例和代码被丢弃 - 不存在!!!
你现在有这个:
所以背后的代码从来没有真正直接与用户交互。
您的代码只能在到服务器的短途旅行期间修改网页。 运行s 后面的代码 - 修改网页,然后将整个页面发送回客户端。
所以你永远不会直接与用户互动,而只会与网页互动,广告只会持续很短的时间。
这意味着什么?
这在很大程度上意味着您可能应该 运行 在网站之外与另一个来源交互的 100% 独立进程。它可以更新 table,然后说您的网站可以有一个定时器重新刷新,重新加载说每 1 或 2 秒。
而且我怀疑如果 10 个用户启动一个网页并且现在所有 10 个用户都开始访问该外部系统,那台机器是否会满意。然而,更糟糕的是什么?
好吧,代码可能会连接到那个盒子,设置一些代码来时不时地接收一些信息,但是如前所述,一旦后面的代码完成,整个网页就会被发送回客户端和服务器端代码+页面被丢弃,不再存在。
只有当您 post 再次返回时,代码广告页面才会从头开始(上次 post 返回时不存在以前的代码值或变量)。
现在,说完上面的内容了吗?
你可以有一个定时器,每 1 或 2 秒触发一次。如果你真的需要从网页到服务器的“实时”连接,那么你会考虑使用所谓的 asp.net signalR。设置起来有点麻烦,所以定时器的想法可能更容易开始。
但是,asp.net signalR 可能是最好的选择。
我知道有很多关于这个特定主题的问题,但我找不到适合我情况的问题。
我的测试应用程序是使用 ASP.Net Web 表单构建的。我使用的库是与 .Net Core 不兼容的 .Net 库,因此我仅限于 .net Framework。
我正在使用提供连接和数据处理的第三方库从 PLC 服务器(使用 TCP/IP 的 Modbus 协议)检索数据,处理程序...我不需要实施“模型”或“控制器”,因为一切都在 类 内处理。这是一个例子:
//References
using AutomatedSolutions.Win.Comm;
using MB = AutomatedSolutions.Win.Comm.MB.Master;
using System;
using System.Text;
using System.Web.UI.WebControls;
protected void Page_Load(object sender, EventArgs e)
{
//Properties Instantiation
mbChannel = new MB.Net.Channel(); //Connection to the server TCP/IP
device1 = new MB.Device(); //Device sending data (temp, speed, ...)
group1 = new MB.Group(false, 500); //Abstract class with a "dataChanged event"
item1 = new MB.Item(); //Represents a specific data point (tag)
group1.Items.Add(item1);
mbChannel.Devices.Add(device1);
device1.Groups.Add(group1);
//Data changed Event Handler
item1.DataChanged += new Item.DataChangedEventHandler(Item_DataChanged);
//Polling activation
group1.Active = true;
}
连接到服务器后,“Item.DataChangedEventHandler”每 500 毫秒触发一次,可以从“项目”中检索新数据。
"Item.DataChangedEventHandler" 代码:
private void Item_DataChanged(object sender, EventArgs evArgs)
{
Item evItem = (Item)sender;
TextBox1.Text = TextBox1.Text + DateTime.Now.ToString("hh:mm:ss:fff") + " Item.DataChange event fired, quality is " + evItem.Quality.ToString();
if (evItem.Quality == AutomatedSolutions.Win.Comm.Quality.GOOD)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < evItem.Elements; i++)
{
sb.Append(evItem.Values[i].ToString() + ",");
}
WriteResult(sb.ToString());
}
}
WriteResults代码:
private void WriteResult(string result)
{
Result.Text = result;
}
DoRead 代码:此函数由按钮动作触发,一次读取一项。这工作正常,读取值显示在“文本框”
private void DoRead(TextBox tb)
{
Result result;
try
{
device1.Read(item1, out result);
if (result.IsOK)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < item1.Elements; i++)
{
sb.Append(item1.Values[i].ToString() + ",");
sb.Length = sb.Length - 1;
tb.Text = sb.ToString();
TextBox1.Text = "Success";
}
}
else
{
TextBox1.Text = TextBox1.Text + result.EvArgs.Message;
}
}
catch (Exception ex)
{
TextBox1.Text = TextBox1.Text + ex.Message;
}
}
我的问题是,虽然使用“DoRead”方法读取项目的值工作正常,但未显示从“dataChanged”事件收集的数据。未触发 TextChanged 事件。
如何使用传入数据更新页面?
嗯,如上所述,您需要掌握 Web 表单或页面的生命周期。
后面的代码只存在于我们所说的往返过程中。
于是,用户请求了一个网页。页面 class 和变量等已创建。 运行s后面的代码,页面发送到客户端。
然后服务器端页面被丢弃 - 不再存在 (现在一遍又一遍地阅读它!!-服务器端代码、变量和页面被丢弃了-它不存在!!!)。
你必须毫无疑问地掌握以上概念。
所以,网页现在被发送到客户端,浏览器重新绘制该页面。它只是坐在用户桌面上,服务器页面 code/page/variable 等现在已经消失了!!!!
最终用户可以拔下他们计算机的插头,也许可以走捷径并转到 google.com。该页面已与网络服务器断开连接!
它从未连接过。该网页就位于用户桌面上。背后的代码早已消失 - 不再存在!!!
Web 服务器因此就坐在那里。它正在等待任何用户的 post-返回。它不会在内存中保存或保留您的网页和代码的副本。 Web 服务器可以接受任何网页请求。
因此,您不能在此过程中运行在网页中保留某些代码。
如果桌面上有网页的 10 个用户中有任何一个点击了按钮?然后,如果发生 post-back,则整个网页将发送到等待该请求的一个 Web 服务器。
然后重新加载页面。页面 class 和变量被重新初始化(从头开始)。现在后面的代码 运行s。您可以更改网页上的内容,只有当所有代码都完成后 运行ning 才会将页面发送回浏览器,然后浏览器会再次重新加载整个页面。
我的意思是,如果该页面有 10 个用户 post 会怎样?您现在拥有该代码和页面的 10 个副本 运行ning!!!!哪个将连接到外部进程??
你有这个设置:
注意页面是如何位于客户端的。在服务器上,没有该页面的实例 class。 (再读一遍这句话!!!)
注意这里非常小心 - 网页在客户端计算机上 - 它根本不存在于网络服务器端。
你没有这个:
你也没有这个:
上面是用户桌面上的网页,然后是服务器上的网页。
你没有那个设置。
页面服务器端不存在。
所以,你有一个网页,你点击了一个按钮:
好的,您点击按钮。现在开始所谓的往返。
所以你点击一个按钮整个网页就是 发送到服务器。你现在有这个:
现在在上面,我想图表可以显示网页也仍然是客户端。但是我把它漏掉了。
现在页面 class 的一个实例已创建,您的后台代码开始 运行ning。
您的隐藏代码可以修改控件(甚至可见),但页面不与用户交互 - 只有代码可以修改网页。
然后将网页发送回客户端,服务器端 class 实例和代码被丢弃 - 不存在!!!
你现在有这个:
所以背后的代码从来没有真正直接与用户交互。
您的代码只能在到服务器的短途旅行期间修改网页。 运行s 后面的代码 - 修改网页,然后将整个页面发送回客户端。
所以你永远不会直接与用户互动,而只会与网页互动,广告只会持续很短的时间。
这意味着什么?
这在很大程度上意味着您可能应该 运行 在网站之外与另一个来源交互的 100% 独立进程。它可以更新 table,然后说您的网站可以有一个定时器重新刷新,重新加载说每 1 或 2 秒。
而且我怀疑如果 10 个用户启动一个网页并且现在所有 10 个用户都开始访问该外部系统,那台机器是否会满意。然而,更糟糕的是什么?
好吧,代码可能会连接到那个盒子,设置一些代码来时不时地接收一些信息,但是如前所述,一旦后面的代码完成,整个网页就会被发送回客户端和服务器端代码+页面被丢弃,不再存在。
只有当您 post 再次返回时,代码广告页面才会从头开始(上次 post 返回时不存在以前的代码值或变量)。
现在,说完上面的内容了吗?
你可以有一个定时器,每 1 或 2 秒触发一次。如果你真的需要从网页到服务器的“实时”连接,那么你会考虑使用所谓的 asp.net signalR。设置起来有点麻烦,所以定时器的想法可能更容易开始。
但是,asp.net signalR 可能是最好的选择。