Cómo llenar el DataGrid en el subproceso en segundo plano con el enlace de datos mediante Visual Basic 2005 o Visual Basic .NET

Id. de artículo: 318604 - Ver los productos a los que se aplica este artículo
Para obtener una versión de Microsoft Visual C# .NET de este artículo, consulte 318607.
Expandir todo | Contraer todo

En esta página

Resumen

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 .
  1. Inicie Visual Studio 2005 o Visual Studio .NET.
  2. Cree un nuevo proyecto, seleccione C# como el Tipo de proyecto y utilice la plantilla Windows Application.
  3. Agregar un objeto Button al formulario y cambie su propiedad Text a "Consultas en subprocesos".
  4. Agregue otro botón al formulario y cambie su propiedad Text a "Consultas en formato".
  5. Agregue una etiqueta al formulario y desactive su propiedad Text .
  6. Agregue un TextBox al formulario.
  7. Agregue un control DataGrid al formulario.
  8. 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.
  9. 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
    					
  10. 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.
  11. Abra la vista de diseño de formularios de Windows.
  12. 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()
    					
  13. 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.
       QueryDataBase()
    					
  14. 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.
  15. 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:
  1. Presione CTRL+F5 para ejecutar la aplicación sin depurar.
  2. 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.
  3. 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):
http://msdn2.microsoft.com/en-us/library/ms379584(vs.80).aspx
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:
http://msdn2.microsoft.com/en-us/library/ms171843.aspx

Referencias

Para obtener más información, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
316422Guí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:
http://msdn2.microsoft.com/en-us/library/3s8xdz5c(vs.71).aspx

Propiedades

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
Palabras clave: 
kbmt kbvs2005swept kbvs2005applies kbhowtomaster KB318604 KbMtes
Traducción automática
IMPORTANTE: 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

Enviar comentarios