Para la versión en inglés, consulte: http://dflying.dflying.net/1/archive/100_building_a_real_time_progressbar_using_aspnet_atlas.html
Cuando algunas operaciones a largo plazo se realizan en segundo plano, sería un logro muy raro si se pudiera proporcionar una barra de progreso en la página para mostrar el progreso real, en lugar de dejar que los usuarios esperen sin saberlo o hagan estimaciones simples en el pasado. lugar. Ahora es completamente posible hacer esto usando ASP.NET Atlas. Este artículo discutirá cómo lograr esta funcionalidad e introducirá algunos conceptos básicos sobre el desarrollo del control del cliente Atlas. También puede descargar programas de muestra y archivos fuente aquí.
La idea de implementar una barra de progreso en una página web es en realidad muy simple: escriba un control Atlas del lado del cliente, solicite al servidor de vez en cuando y use los datos de progreso actuales devueltos para actualizar la visualización de la barra de progreso. . En este ejemplo, habrá cuatro partes de código:
un servicio web que tarda mucho en completarse
Un servicio web utilizado para consultar el progreso del servicio web anterior.
El control de la barra de progreso del Atlas del cliente (ProgressBar) es responsable de mantener la lógica del cliente y generar la interfaz de usuario visual. Este también es el componente más importante en este ejemplo y se puede reutilizar en el desarrollo de otras páginas o programas en el futuro. Una página de prueba de ASP.NET que contiene el servicio web y los controles anteriores. A continuación, implementamos los cuatro pasos anteriores paso a paso. :
lleva mucho tiempo Servicio web que tarda mucho en completarse
En un programa real, un servicio web que tarda mucho en completarse puede tener la siguiente declaración:
1[WebMethod]
2tarea de consumo de tiempo pública vacía ()
3{
4 ConectarToDataBase();
5 GetSomeValueFromDataBase();
6 CopiarAlgunosArchivosDesdeDisk();
7 ObtenerARemoteFile();
8}
De esta manera, podemos insertar algunos métodos auxiliares para determinar el estado de finalización del progreso actual. setProgress(int) se utiliza para establecer el porcentaje de finalización del progreso actual:
1[WebMethod]
2tarea de consumo de tiempo pública vacía ()
3{
4 establecerProgreso(0);
5ConnectToDataBase();
6 establecerProgreso(10);
7 GetSomeValueFromDataBase();
8 establecerProgreso(40);
9 Copiar algunos archivos del disco();
10 setProgreso(50);
11 ObtenerARemoteFile();
12 setProgreso(100);
13}
En este ejemplo, solo usamos Cache para almacenar información de finalización del progreso y usamos el método Thread.Sleep() para simular el retraso de la operación:
1[WebMethod]
2público int StartTimeConsumingTask()
3{
ProcessKey de 4 cadenas = this.Context.Request.UserHostAddress;
5 cadenas threadLockKey = "hilo" + this.Context.Request.UserHostAddress;
6 objeto threadLock = this.Context.Cache[threadLockKey];
7 si (threadLock == nulo)
8 {
9 threadLock = nuevo objeto();
10 this.Context.Cache[threadLockKey] = threadLock;
11 }
12
13 // Solo permite 1 tarea en ejecución por usuario.
14 si (!Monitor.TryEnter(threadLock, 0))
15 retorno -1;
16
17 FechaHora horaInicio = FechaHora.Ahora;
18
19 // Simule una tarea que requiere mucho tiempo.
20 para (int i = 1; i <= 100; i++)
veintiuno {
22 // Actualiza el progreso de esta tarea.
23 this.Context.Cache[processKey] = i;
24 hilos. Dormir (70);
25}
26
27 Monitor.Salir(threadLock);
28
29 retorno (DateTime.Now - startTime).Segundos;
30}
31
El servicio web para consultar el progreso
es fácil de implementar, solo obtenga la información del progreso del caché:
1[WebMethod]
2público int GetProgress()
3{
ProcessKey de 4 cadenas = this.Context.Request.UserHostAddress;
5 progreso del objeto = this.Context.Cache[processKey];
6 si (progreso! = nulo)
7 {
8 retorno (int)progreso;
9}
10
11 devuelve 0;
12}
Control de la barra de progreso del lado del cliente (ProgressBar)
Paso 1: heredar de Sys.UI.Control
El control ProgressBar debe heredar de la clase base del control Atlas Sys.UI.Control y declararlo como una clase sellada (clase sellada, que puede ya no se puede heredar) ). La clase base Sys.UI.Control contiene algunas operaciones y métodos comunes a todos los controles. Por ejemplo, asociarse con un elemento HTML (también conocido como enlace), etc. Al mismo tiempo, debe registrarse para que Atlas conozca este nuevo tipo para su futura declaración y uso, por ejemplo, para que Atlas pueda obtener la descripción de este tipo, etc.
1Sys.UI.ProgressBar = función (elemento asociado) {
2 Sys.UI.ProgressBar.initializeBase (esto, [elemento asociado]);
3
4}
5Type.registerSealedClass('Sys.UI.ProgressBar', Sys.UI.Control);
6Sys.TypeDescriptor.addType('script','progressBar', Sys.UI.ProgressBar);
7
Paso 2: Agregue miembros privados y escriba el Setter/Getter correspondiente.
A continuación, debe agregar algunas propiedades para configurar nuestro control. En este ejemplo, necesitamos tres propiedades:
Intervalo. El intervalo entre cada vez que se vuelve a consultar el progreso y se actualiza la barra de progreso. Unidad: milisegundo
URL del servicio. La ruta del archivo del servicio web.
Método de servicio. El nombre del método para obtener información de progreso.
Estas propiedades deben seguir estrictamente la convención de nomenclatura de Atlas: los captadores deben comenzar con 'get_' y los setter deben comenzar con 'set_' y pasar un parámetro. También debe agregar descripciones de estas propiedades en el descriptor del control. El método de descripción (descriptor) se explicará en el cuarto paso. Por ejemplo, para el atributo Método de servicio, tenemos la siguiente declaración:
1var _serviceMethod;
2
3this.get_serviceMethod = función() {
4 retorno _serviceMethod;
5}
6
7this.set_serviceMethod = función (valor) {
8 _serviceMethod = valor;
9}
Paso 3: Utilice el control Temporizador para consultar el
sistema de servicios web de vez en cuando. El temporizador se utiliza para llamar a un método (emitir un evento) cada vez. Podemos definir un delegado para que apunte a este método y hacerlo cada vez. Consultar este Servicio Web dentro de un periodo de tiempo. Para evitar pérdidas de memoria del navegador, debe recordar realizar la limpieza necesaria cuando se destruya (elimine) el control.
Además, tenga en cuenta que no debe enviar una segunda solicitud cuando la solicitud anterior no haya regresado.
1var _timer = nuevo Sys.Timer();
2var _responsePendiente;
3var _tickHandler;
4var _obj = esto;
5
6this.initialize = función() {
7 Sys.UI.ProgressBar.callBaseMethod(esto, 'inicializar');
8 _tickHandler = Function.createDelegate(esto, esto._onTimerTick);
9 _timer.tick.add(_tickHandler);
10 this.set_progress(0);
11}
12
13this.dispose = función() {
14 si (_temporizador) {
15 _timer.tick.remove(_tickHandler);
16 _tickHandler = nulo;
17 _timer.dispose();
18}
19 _temporizador = nulo;
20 elemento asociado = nulo;
21 _obj = nulo;
Veintidós
23 Sys.UI.ProgressBar.callBaseMethod(esto, 'eliminar');
veinticuatro}
25
26this._onTimerTick = función (remitente, eventArgs) {
27 si (!_responsePending) {
28 _responsePending = verdadero;
29
30 // Llama asincrónicamente al método de servicio.
31 Sys.Net.ServiceMethod.invoke(_serviceURL, _serviceMethod, nulo, nulo, _onMethodComplete);
32}
33}
34
35función _onMethodComplete(resultado) {
36 // Actualiza la barra de progreso.
37 _obj.set_progress(resultado);
38 _responsePending = falso;
39}
Paso 4: Agregar método de control
Deberíamos poder controlar el inicio/detención de la barra de progreso. Además, para un control Atlas, el método de descripción relacionado (descriptor) también es necesario. Atlas lo utilizará para describir este tipo de información.
1this.getDescriptor = función() {
2 var td = Sys.UI.ProgressBar.callBaseMethod(this, 'getDescriptor');
3 td.addProperty('intervalo', Número);
4 td.addProperty('progreso', Número);
5 td.addProperty('servicioURL', Cadena);
6 td.addProperty('serviceMethod', Cadena);
7 td.addMethod('inicio');
8 td.addMethod('detener');
9 retorno td;
10}
11
12this.start = función() {
13 _timer.set_enabled (verdadero);
14}
15
16this.stop = función() {
17 _timer.set_enabled(falso);
18}
Bien, el control del cliente está completo hasta ahora. Lo guardamos como ProgressBar.js.
Página de prueba de ASP.NET Página de prueba de ASP.NET
Para cualquier página de Atlas, lo primero que debemos hacer es agregar un control de servidor ScriptManager. En este ejemplo nos referiremos al control ProgressBar, al servicio web que tarda mucho en completarse y al servicio web Progress Query. (Estos dos servicios web se encuentran en el mismo archivo: TaskService.asmx)
1<atlas:ScriptManager ID="ScriptManager1" runat="server" >
2 <Guiones>
3 <atlas:ScriptReference Path="ScriptLibrary/ProgressBar.js" ScriptName="Personalizado" />
4 </guiones>
5 <Servicios>
6 <atlas:ServiceReference Path="TaskService.asmx" />
7 </Servicios>
8</atlas:ScriptManager>
El siguiente es el diseño y estilo de la página:
1<style type="text/css">
2* {}{
3 familias de fuentes: tahoma;
4}
5.contenedor de barra de progreso {}{
6 borde: 1px sólido #000;
7 ancho: 500 px;
8 altura: 15px;
9}
10. barra de progreso {}{
11 color de fondo: verde;
12 altura: 15px;
13 ancho: 0px;
14 peso de fuente: negrita;
15}
16</estilo>
17
18<div>Progreso de la tarea</div>
19<div class="progressBarContainer">
20 <div id="pb" class="barra de progreso"></div>
21</div>
22<input type="button" id="start" onclick="startTask();return false;" value="¡Inicie la tarea que requiere mucho tiempo!"
23<div id="salida" >>div>
Finalmente, hay un fragmento de JavaScript para iniciar el Servicio Web que tarda mucho en completarse y dejar que el control ProgressBar comience a funcionar:
Capturas de pantalla y descargas
¡Ahora todo está hecho y listo para funcionar!
Inicialización de página:
Correr:
Ejecución completada:
Los programas de muestra y los archivos fuente se pueden descargar aquí .