基于优先级的异步回发调度程序





4.00/5 (2投票s)
一个根据优先级调度异步回发的组件
引言
在文章 同时启用多个异步回发[^] 中,Vinay Lakhanpal[^] 讨论了以 FIFO 方式(先进先出)调度异步回发。 在本文中,我们将基于给定的优先级来调度这些回发。 因此,紧急的回发将首先被处理。
背景
本文基于 同时启用多个异步回发[^] 中 Vinay Lakhanpal[^] 讨论的思路。
实现
首先,我们将创建一个自定义控件。 这将有助于重用。 因此,我们从 WebControl
类扩展并实现 IScriptControl
接口。 此接口将通过其 GetScriptReferences()
方法访问嵌入式脚本资源。
Protected Overridable Function GetScriptReferences() _
As IEnumerable(Of ScriptReference) Implements IScriptControl.GetScriptReferences
Dim reference As New ScriptReference()
reference.Assembly = "AsyncScheduling"
reference.Name = "AsyncScheduling.AsyncSceduler.js"
Return New ScriptReference() {reference}
End Function
接口 IScriptControl
提供的另一个方法是 GetScriptDescriptors()
; 它提供了 JavaScript 类的类型描述方式。 但由于我们不需要定义对象(JavaScript 对象),甚至不需要向文档添加 HTML DOM 元素,因此我们不需要提供任何类型描述符。 我们只需返回一个空数组。
Protected Overridable Function GetScriptDescriptors() _
As IEnumerable(Of ScriptDescriptor) Implements IScriptControl.GetScriptDescriptors
Return New ScriptDescriptor() {}
End Function
然后我们定义 JavaScript 类
EventReference
:表示回发的事件目标和事件参数对。Node
:表示要推入队列的节点。ReadyQueue
:表示将排列回发事件引用的队列。- 最后是
AsyncSceduler
:这是处理PageRequestMaanager
initializeRequest
和endRequest
事件的主要组件。
AsyncSceduler
AsyncSceduler
类提供了一些 static
(共享)字段和方法,这些字段和方法有助于调度过程。 这些字段是
prm
,类型为Sys.WebForms.PageRequestManager
,它通过事件管理异步回发pendingRequest
,类型为Ready Queue
,它保存准备传递到服务器的回发prioritytable
,类型为Array
,它表示控件唯一 ID/优先级对的哈希表logmethode
,类型为String
,它是用于日志记录的 JavaScript 函数的名称
方法有
initialize(logmethod)
,它初始化AsyncScheduler
的通用逻辑initializeRequest
,它在初始化请求时执行endRequest
,它在初始化请求时执行TriggerPendingPostBack
,它将请求传递到服务器
队列
队列的思想是根据节点的优先级来排列节点,优先级是 Priority
值之一:Real Time、High、Above Normal、Normal、Below Normal、Low,因此最高优先级将被首先服务。
队列由两个指针组成,头 (head) 和尾 (tail),指向指针数组(节点); 一个指向第一个节点,另一个指向最后一个节点。 每个节点都有一个指针指向后面的节点,最后一个节点不指向任何内容(null
)。 节点还具有 EventReference
类的实例,用于保存回发和优先级值。

一旦我们将事件引用以给定的优先级推入队列,我们首先创建一个具有给定值的节点,我们根据优先级确定放置节点的位置,我们切断两个节点之间的连接,然后我们设置连接以通过我们的节点。
Using the Code
要使用 AsyncSceduler
,我们首先需要在标记文件中标记到一个公共位置,例如母版页
<%@ Register Assembly="AsyncScheduling" Namespace="AsyncScheduling" TagPrefix="cc1" %>
<cc1:AsyncSceduler ID="AsyncSceduler1" runat="server" />
然后我们可以通过 GetCurrent()
方法从内容页面调用它,我们只需通过 SetAsyncControlPriority()
方法设置控件的优先级。
Dim AsyncSceduler1 As AsyncScheduling.AsyncSceduler =
AsyncScheduling.AsyncSceduler.GetCurrent(Me)
AsyncScedular1.LogMethod = "WriteLog"
AsyncSceduler1.SetAsyncControlPriority(Button1, AjaxServerControl1.Priority.High)
AsyncSceduler1.SetAsyncControlPriority(Button2, AjaxServerControl1.Priority.AboveNormal)
AsyncSceduler1.SetAsyncControlPriority(Button3, AjaxServerControl1.Priority.Normal)
AsyncSceduler1.SetAsyncControlPriority(Button4, AjaxServerControl1.Priority.Low)
AsyncSceduler1.SetAsyncControlPriority(Button5, AjaxServerControl1.Priority.BelowNormal)
AsyncSceduler1.SetAsyncControlPriority(Button6, AjaxServerControl1.Priority.RealTime)
看点
因为此组件没有与之关联的元素,所以我们只需添加一个 static
调用来初始化通用逻辑。 我们使用 Page.ClientScript
在 Control.Render()
方法期间注册此代码块,就像
Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
If Not Me.DesignMode Then
sMgr.RegisterScriptDescriptors(Me)
End If
Dim builder As New Text.StringBuilder(String.Format_
("AsyncScheduling.AsyncSceduler.initialize('{0}');" & vbCrLf, Me.LogMethod))
For Each _uniqueid As String In PriortyTable.Keys
builder.AppendFormat("AsyncScheduling.AsyncSceduler.prioritytable['{0}'] = _
AsyncScheduling.Priority.{1};" & vbCrLf, _uniqueid, PriortyTable(_uniqueid))
Next
Me.Page.ClientScript.RegisterStartupScript(GetType(AsyncSceduler), _
"AsyncSceduler", builder.ToString, True)
MyBase.Render(writer)
End Sub
历史
- 2011 年 5 月 27 日星期五:第一个版本
- 2011 年 6 月 9 日星期四:转换了 JavaScript 类以提供
static
成员并添加了一个部分来描述它