Cuando se ejecutan las consultas grandes a una base de datos, la aplicación puede no responder durante un largo período de tiempo. Para evitar este comportamiento y reducir el tiempo de espera del usuario, se puede ejecutar la consulta en un subproceso de fondo, liberando la aplicación para otras tareas hasta que se devuelven los datos de la base de datos y se realiza el enlace de datos.
Este artículo paso a paso muestra cómo consultar una base de datos en un subproceso en segundo plano y utilizar enlace de datos para mostrar los resultados en un objeto
DataGrid .
Requisitos
En la lista siguiente se describe el hardware, el software, la infraestructura de red y los service pack recomendados que se necesitarán:
- Microsoft Visual Studio 2005 o Microsoft Visual Studio .NET
- Acceso a la base de datos Northwind de ejemplo
Fondo
Por diseño, Microsoft Windows Forms o métodos de control no pueden llamarse en un subproceso distinto del que creó el formulario o control. Si intenta hacerlo, se produce una excepción. En función de control de excepciones implementado en el código, esta excepción puede hacer que su aplicación terminar. Si no se implementa ningún control de excepciones, se muestra el mensaje de error siguientes:
Excepción no controlada del tipo 'System.ArgumentException' se ha producido en system.windows.forms.dll
Obtener información adicional: no se pueden tener controles primarios controles creados en un subproceso a un control en un subproceso diferente.
La excepción se produce porque se basa en un modelo de apartamento de un único subproceso (STA). Formularios Windows Forms puede crearse en cualquier subproceso; una vez creadas, sin embargo, no se puede cambiar a un subproceso diferente. Además, Imposible tener acceso a los métodos de formularios Windows Forms desde otro subproceso; Esto significa que todas las llamadas de método deben ejecutarse en el subproceso que creó el formulario o control.
Las llamadas a métodos que se originen fuera el subproceso de creación deben calcularse (ejecutado) en el subproceso de creación. Para ello de forma asincrónica, el formulario tiene un método
BeginInvoke que obliga a que el método que se va a ejecutar el subproceso que creó el formulario o control. La llamada al método sincrónico se realiza con una llamada al método
Invoke .
Generar la aplicación de formularios Windows Forms
Esta sección describe cómo crear una aplicación de formularios Windows Forms que consulta una base de datos en un subproceso en segundo plano y utiliza el método
BeginInvoke para realizar el enlace de datos en un
DataGrid .
- Inicie Visual Studio 2005 o Visual Studio .NET.
- Cree un nuevo proyecto, seleccione C# como el Tipo de proyecto y utilice la plantilla Windows Application.
- Agregar un objeto Button al formulario y cambie su propiedad Text a "Consultas en subprocesos".
- Agregue otro botón al formulario y cambie su propiedad Text a "Consultas en formato".
- Agregue una etiqueta al formulario y desactive su propiedad Text .
- Agregue un TextBox al formulario.
- Agregue un control DataGrid al formulario.
- Haga clic con el botón secundario en el formulario y, a continuación, haga clic en Ver código ; Esto muestra el código de la aplicación.
- Agregue las siguientes instrucciones de importación a la parte superior de la página para importar los espacios de nombres subprocesamiento y SqlClient .
Imports System.Threading
Imports System.Data.SqlClient
- Agregue el código siguiente inmediatamente debajo de los formularios Windows Forms Designer Generated Code.
Dim UpdateThread As Thread
Dim UpdateThreadStart As New ThreadStart(AddressOf QueryDataBase)
Dim CallDataBindToDataGrid As New MethodInvoker(AddressOf Me.DataBindToDataGrid)
Dim MyDataSet As DataSet
Dim MyDataAdapter As SqlDataAdapter
Dim MyQueryString As String = "SELECT Products.* FROM [Order Details] CROSS JOIN Products"
Dim MyConnection As New SqlConnection("data source=localhost;initial catalog=northwind;integrated security=SSPI;")
Nota la consulta utilizada en esta demostración es un producto cartesiano que devuelve 165,000 a través filas de la base de datos Northwind . La cantidad de datos devueltos es grande, por lo que se puede demostrar la capacidad de respuesta del formulario. - Abra la vista de diseño de formularios de Windows.
- Haga doble clic en el botón consulta en el subproceso y pegue el código siguiente en el evento Click para este botón.
UpdateThread = New Thread(UpdateThreadStart)
UpdateThread.IsBackground = True
UpdateThread.Name = "UpdateThread"
UpdateThread.Start()
- Abra la vista Diseño de nuevo y, a continuación, haga doble clic en el botón de consulta en el formulario . Pegue el código siguiente en el evento Click para este botón.
- Pegue el código siguiente debajo de los eventos de botón que agregó en los pasos anteriores.
' Sub routine that is to be executed on Form's thread.
Public Sub DataBindToDataGrid()
DataGrid1.DataSource = MyDataSet
DataGrid1.DataMember = "MyTable"
MyDataAdapter = Nothing
MyDataSet = Nothing
End Sub
' Sub routine used by the background thread to query database.
Public Sub QueryDataBase()
MyDataSet = New DataSet()
MyConnection.Open()
Dim cmd As New SqlCommand(MyQueryString, MyConnection)
MyDataAdapter = New SqlDataAdapter(cmd)
Label1.Text = "Filling DataSet"
MyDataAdapter.Fill(MyDataSet, "MyTable")
MyConnection.Close()
Label1.Text = "DataSet Filled"
' Make asynchronous function call to Form's thread.
Me.BeginInvoke(CallDataBindToDataGrid)
End Sub
Sub these rutinas utilizan el subproceso de fondo para consultar la base de datos y enlace de datos que el control DataGrid encuentra en el formulario Windows Forms cuando se hace clic en el primer botón. El evento Click del segundo botón llama a la rutina de QueryDataBase Sub directamente y se ejecutará en los formularios Windows Forms subproceso. - Presione CTRL + MAYÚS + B para generar la aplicación.
Demostración
Para ver el beneficio obtenido mediante un subproceso de fondo para consultar la base de datos, siga estos pasos:
- Presione CTRL+F5 para ejecutar la aplicación sin depurar.
- Haga clic en consulta en el formulario . Se inicia la consulta en el subproceso de formularios Windows Forms. Si a continuación, intenta escribir texto en el cuadro de texto que se muestra en el formulario, la aplicación no responde. Una vez finalizada la consulta (puede tardar algún tiempo, según el equipo), el control DataGrid muestra los resultados de la consulta.
- Haga clic en el botón de consulta en el subproceso . Esto crea un subproceso de fondo que consulta la base de datos y mantiene la aplicación responde a la interacción del usuario. Para ver esto, haga clic en el botón y, a continuación, escriba algún texto en el cuadro de texto en el formulario.
Listado de código completo
Imports System.Threading
Imports System.Data.SqlClient
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call.
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer.
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer.
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Public WithEvents DataGrid1 As System.Windows.Forms.DataGrid
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.DataGrid1 = New System.Windows.Forms.DataGrid()
Me.Button1 = New System.Windows.Forms.Button()
Me.Button2 = New System.Windows.Forms.Button()
Me.Label1 = New System.Windows.Forms.Label()
Me.TextBox1 = New System.Windows.Forms.TextBox()
CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'DataGrid1
'
Me.DataGrid1.DataMember = ""
Me.DataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText
Me.DataGrid1.Location = New System.Drawing.Point(8, 8)
Me.DataGrid1.Name = "DataGrid1"
Me.DataGrid1.Size = New System.Drawing.Size(688, 276)
Me.DataGrid1.TabIndex = 0
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(12, 296)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(136, 23)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Query on Thread"
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(160, 296)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(132, 23)
Me.Button2.TabIndex = 3
Me.Button2.Text = "Query on Form"
'
'Label1
'
Me.Label1.Font = New System.Drawing.Font("Microsoft Sans Serif", 15.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Label1.Location = New System.Drawing.Point(12, 332)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(680, 23)
Me.Label1.TabIndex = 4
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(300, 296)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(392, 20)
Me.TextBox1.TabIndex = 5
Me.TextBox1.Text = ""
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(704, 382)
Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.TextBox1, Me.Label1, Me.Button2, Me.Button1, Me.DataGrid1})
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
#End Region
Dim UpdateThread As Thread
Dim UpdateThreadStart As New ThreadStart(AddressOf QueryDataBase)
Dim CallDataBindToDataGrid As New MethodInvoker(AddressOf Me.DataBindToDataGrid)
Dim MyDataSet As DataSet
Dim MyDataAdapter As SqlDataAdapter
Dim MyQueryString As String = "SELECT Products.* FROM [Order Details] CROSS JOIN Products"
Dim MyConnection As New SqlConnection("data source=localhost;initial catalog=northwind;integrated security=SSPI;")
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
UpdateThread = New Thread(UpdateThreadStart)
UpdateThread.IsBackground = True
UpdateThread.Name = "UpdateThread"
UpdateThread.Start()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
QueryDataBase()
End Sub
Public Sub DataBindToDataGrid()
DataGrid1.DataSource = MyDataSet
DataGrid1.DataMember = "authors"
MyDataAdapter = Nothing
MyDataSet = Nothing
End Sub
Public Sub QueryDataBase()
MyDataSet = New DataSet()
MyConnection.Open()
Dim cmd As New SqlCommand(MyQueryString, MyConnection)
MyDataAdapter = New SqlDataAdapter(cmd)
Label1.Text = "Filling DataSet"
MyDataAdapter.Fill(MyDataSet, "authors")
MyConnection.Close()
Label1.Text = "DataSet Filled"
Me.BeginInvoke(CallDataBindToDataGrid)
End Sub
End Class
Nota Debe cambiar el código en Visual Basic 2005. De forma predeterminada, Visual Basic crea dos archivos para el proyecto cuando se crea un proyecto de formularios Windows Forms. Si el formulario se denomina Form1, los dos archivos que representan el formulario se denominan Form1.vb y Form1.Designer.vb. Escribir el código en el archivo Form1.vb. El Diseñador de Windows Forms escribe el código en el archivo Form1.Designer.vb. El Diseñador de Windows Forms se utiliza la palabra clave partial para dividir la implementación de Form1 en dos archivos independientes. Este comportamiento evita que el código generado por diseñador se mezcle suyo con su código.
Para obtener más información acerca de las nuevas mejoras del lenguaje Visual Basic 2005, visite el siguiente sitio Web de Microsoft Developer Network (MSDN):
Para obtener más información acerca de las clases parciales y el Diseñador de Windows Forms, visite el siguiente sitio Web de MSDN:
Para obtener más información, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
316422
(http://support.microsoft.com/kb/316422/
)
Guía básica para el subprocesamiento en Visual Basic.NET
Para ver un ejemplo multiproceso de Windows Forms controlar, visite el siguiente sitio Web de MSDN:
Id. de artículo: 318604 - Última revisión: miércoles, 16 de mayo de 2007 - Versión: 3.6
La información de este artículo se refiere a:
- Microsoft Visual Basic 2005
- Microsoft Visual Basic .NET 2003 Standard Edition
- Microsoft Visual Basic .NET 2002 Standard Edition
- Microsoft ADO.NET 1.0
| kbmt kbvs2005swept kbvs2005applies kbhowtomaster KB318604 KbMtes |
Traducción automáticaIMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés):
318604
(http://support.microsoft.com/kb/318604/en-us/
)