Pos no me he rendido con los THREADS

04/01/2006 - 20:47 por Ch0rY | Informe spam
rendirme no es lo mio, cansarme si, pero rendirme no.

Asi q estoy de vuelta con el tema

Si recordais, tenia intencion de hacer unos threads para "operar" con
varios archivos o varias filas de un listview a la vez.

Al principio no fui capaz de crear un simple thread, hoy lo he conseguido y
he sido capaz de crear una clase q lo use.

Pero no se como hacer q se ejecute 4 veces simultaneamente

Este es el proyecto q he creado

En un form, metemos un listview llamado lst_View y cuatro botones
(btn_h1,btn_h2,btn_h3,btn_h4)

Este es el codigo en el form

Imports System.Threading

Public Class Form1
Dim Hilin(3) As Pilla
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
Me.Dispose()
End
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim Contador As Byte
Dim lvwItem As ListViewItem
For Contador = 1 To 254
lvwItem = New ListViewItem(Contador.ToString)
lvwItem.SubItems.Add("")
lst_View.Items.Add(lvwItem)
Next
End Sub

Private Sub btn_h1.Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btn_h1.Click, btn_h2.Click, btn_h3.Click,
btn_h4.Click
Dim Contador As Byte
For Contador = 0 To 4
If IsNothing(Hilin(Contador)) Then
Hilin(Contador) = New Pilla
If Not Hilin(Contador).Iniciado Then
Hilin(Contador).lista = Me.lst_View
Hilin(Contador).Iniciar()
Exit Sub
End If
End If
Next
End Sub
End Class

y esta es la clase que he creado (PILLA)

Imports System.Threading

Public Class Pilla
Delegate Sub Hazlo()
Public ElHilo As Thread = Nothing
Public lista As ListView

Private _Iniciado As Boolean

ReadOnly Property Iniciado() As Boolean
Get
Iniciado = _Iniciado
End Get
End Property

Public Sub Hilo()
Dim lvwItem As ListViewItem
_Iniciado = True
If lista.InvokeRequired Then
Dim Hilo2 As New Hazlo(AddressOf Hilo)
lista.Invoke(Hilo2)
Else
For Each lvwItem In lista.Items
If lvwItem.Checked Then Exit For
lvwItem.Checked = True
Dim Contador As Integer
For Contador = 0 To 65000
Application.DoEvents()
lvwItem.SubItems(1).Text = Format("0.00", Contador).ToString
Next
Next
End If
_Iniciado = False
End Sub

Public Sub Iniciar()
ElHilo = New Thread(New ThreadStart(AddressOf Hilo))
ElHilo.Start()
End Sub

End Class


Me gustaria q lo echaseis un vistazo y si no podeis decirme como hacer lo
que quiero, si me gustaria me dijerais, q os parece, q fallos veis q estoy
cometiendo, y tal y tal...


Gracias de nuevo.

Reconocereis q como cura no tendria precio, tol dia pidiendo :D

Preguntas similare

Leer las respuestas

#1 Jesús López
05/01/2006 - 13:14 | Informe spam
Bueno, en realidad creo que no lo estás enfocando bien. La cuestión no es
actualizar un listview usando varios hilos, sino hacer una o varias tareas
en segundo plano usando hilos e ir actualizando el listview en función del
progreso o terminación de esas tareas. De forma más genérica lo diríamos
así: la aplicación realiza una o varias tareas en segundo plano y va
actualizando el interfaz del usuario según se van realizando dichas tareas.
Uno de los fines de este diseño es que el interfaz del usuario no se quede
congelado o aparentemente colgado mientras se realizan tareas de
relativamente larga duración. Otro de los fines es tardar menos tiempo en
realizar varias tareas si esas tareas pueden hacerse en paralelo.

Uno de los "fallos" que tiene el código que has puesto aquí, es que en
realidad prácticamente nada se está ejecutando en los hilos que creas. El
método que es el punto de entrada de los hilos:

Public Sub Hilo()
Dim lvwItem As ListViewItem
_Iniciado = True
If lista.InvokeRequired Then
Dim Hilo2 As New Hazlo(AddressOf Hilo)
lista.Invoke(Hilo2)
Else
For Each lvwItem In lista.Items
If lvwItem.Checked Then Exit For
lvwItem.Checked = True
Dim Contador As Integer
For Contador = 0 To 100
Application.DoEvents()
lvwItem.SubItems(1).Text = Format("0.00",
Contador).ToString
Next
Next
End If
_Iniciado = False
End Sub

Lista.InvokeRequired siempre va a devolver True la primera vez, ya que Sub
Hilo() se está ejecutando en un hilo diferente del que creó el listview. Por
tanto se ejecutará lista.Invoke(Hilo2) lo que provoca que se ejecute Sub
Hilo() en el hilo que creó el listview o sea el hilo principal de la
aplicación, no el hilo que has creado. En consecuencia la gran parte del
trabajo (lo que hay en el Else) se está ejecutando en el hilo principal. Por
eso has tenido que poner DoEvents, si no, la aplicación parecería colgada.
Esto es así porque en realidad el trabajo no se está ejecutando en segundo
plano sino en primer plano.

Otras cosas que me "chocan" en el código es que tengas cuatro botones que
hacen exáctamente lo mismo, con uno habría bastado.


Hay dos razones por las que no se ejecutan las cosas cuatro veces al mismo
tiempo:

(1) Lo que te he dicho de que en realidad tus hilos no hacen nada, sino que
el trabajo se ejecuta en el hilo principal.
(2) La línea de código If lvwItem.Checked then Exit For. Una vez hecho algo
con un item ya no se vuelve a hacer nada.


Mi recomendación es que hagas tres cosas:

(1) Leas la documentación
(2) Leas la documentación
(3) Leas la documentación

Creo que deberías empezar por lo más sencillo que es el componente
Background Worker:

http://msdn2.microsoft.com/en-us/library/c8dcext2(en-US,VS.80).aspx

Depués deberías seguir con los patrones de diseño en programación asíncrona:

http://msdn2.microsoft.com/en-us/library/ms228969(en-US,VS.80).aspx

Y bueno, aquí tienes un ejemplo de implementación del patrón asíncrono
basado en eventos, en el que utilizo hilos en vez de la clase
AsyncOperationManager que sugiere la documentación. La implementación que he
hecho del patrón no es muy estricta, pero sigue su esencia.

Este ejemplo se basa en una clase ContactsLoader que va obteniendo todos los
contactos de la tabla Person.Contact de la base de datos AdventureWorks:
http://www.microsoft.com/downloads/...x?FamilyIDç19ecf7-9f46-4312-af89-6ad8702e4e6e&DisplayLang=en

ContacstLoader abre la conexión, ejecuta la instrucción select y recupera
los datos de la base de datos en segudo plano (un hilo). Cada vez que
recupera un registro lanza un evento informando de ese registro. El
lanzamiento del evento se ejecuta en primer plano para evitar problemas de
sincronización con los controles windows forms. Para eso utiliza
SynchronizationContext.

El ejemplo es un formulario con un botón, un gridview y un progress bar.
Este es el código:

Imports System.Threading

Imports System.ComponentModel



Public Class frmContacts

Dim WithEvents Loader As New ContactsLoader

Dim ContactsList As New BindingList(Of Contact)

Dim ContactsCount As Integer

Dim ContactsLoaded As Integer



Private Sub Loader_ContactRetreived(ByVal sender As Object, ByVal e As
ContactRetreivedEventArgs) Handles Loader.ContactRetreived

ContactsLoaded += 1

Me.ContactsProgressBar.Value = ContactsLoaded * 100 / ContactsCount

ContactsList.Add(e.Contact)

End Sub



Private Sub Loader_OperationCompleted(ByVal sender As Object, ByVal e As
OperationCompletedEventArgs) Handles Loader.OperationCompleted

If e.Success Then

Me.ContactsProgressBar.Visible = False

Else

MsgBox("Error al cargar los contactos: " & vbNewLine & vbNewLine
& e.Exception.Message, MsgBoxStyle.Critical)

End If

Me.LoadContactsButton.Enabled = True

End Sub



Private Sub LoadContactsButton_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles LoadContactsButton.Click

ContactsLoaded = 0

Me.ContactsProgressBar.Visible = True

Me.ContactsProgressBar.Value = 0

Me.LoadContactsButton.Enabled = False

Me.ContactsList.Clear()

Loader.LoadAsync()

End Sub



Private Sub frmContacts_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Me.grid.DataSource = Me.ContactsList

Me.ContactsCount = Me.Loader.GetContactsCount()

Me.ContactsProgressBar.Visible = False

End Sub

End Class





Public Class Contact



Private _ContacId As Integer

Public Property ContactId() As Integer

Get

Return _ContacId

End Get

Set(ByVal value As Integer)

_ContacId = value

End Set

End Property





Private _FirstName As String

Public Property FirstName() As String

Get

Return _FirstName

End Get

Set(ByVal value As String)

_FirstName = value

End Set

End Property





Private _LastName As String

Public Property LastName() As String

Get

Return _LastName

End Get

Set(ByVal value As String)

_LastName = value

End Set

End Property





Private _Email As String

Public Property Email() As String

Get

Return _Email

End Get

Set(ByVal value As String)

_Email = value

End Set

End Property



End Class



Public Class ContactRetreivedEventArgs

Inherits EventArgs

Private _Contact As Contact

Public ReadOnly Property Contact() As Contact

Get

Return _Contact

End Get

End Property



Public Sub New(ByVal Contact As Contact)

_Contact = Contact

End Sub

End Class



Public Class OperationCompletedEventArgs

Inherits EventArgs



Private _Success As Boolean

Public ReadOnly Property Success() As Boolean

Get

Return _Success

End Get

End Property





Private _Exception As Exception

Public ReadOnly Property Exception() As Exception

Get

Return _Exception

End Get

End Property



Public Sub New(ByVal Exception As Exception)

_Exception = Exception

_Success = Exception Is Nothing

End Sub



End Class



Public Class ContactsLoader

Public Event ContactRetreived As EventHandler(Of
ContactRetreivedEventArgs)

Public Event OperationCompleted As EventHandler(Of
OperationCompletedEventArgs)



Private Context As SynchronizationContext

Private WorkingThread As Thread

Private OnContactRetreivedCallBack As SendOrPostCallback = New
SendOrPostCallback(AddressOf OnContactRetreived)

Private OnOperationCompletedCallBack As SendOrPostCallback = New
SendOrPostCallback(AddressOf OnOperationCompleted)



Public Sub LoadAsync()

If IsInProgress Then

Throw New InvalidOperationException("No se pueden cargar otra
vez los contactos mientras se están cargando")

End If

Context = SynchronizationContext.Current

WorkingThread = New Thread(AddressOf BackgroundLoad)

WorkingThread.Priority = ThreadPriority.BelowNormal

WorkingThread.Start()

End Sub



Public Sub Cancel()

If IsInProgress Then

WorkingThread.Abort()

End If

End Sub



Private ReadOnly Property IsInProgress() As Boolean

Get

Return WorkingThread IsNot Nothing AndAlso WorkingThread.IsAlive

End Get

End Property



Private Sub BackgroundLoad()

Dim cn As New SqlClient.SqlConnection("Data
Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks")

Dim cmd As New SqlClient.SqlCommand("select ContactID, FirstName,
LastName, EmailAddress from Person.Contact", cn)

Dim reader As SqlClient.SqlDataReader = Nothing

Try

cn.Open()

reader = cmd.ExecuteReader()

While reader.Read()

Dim Contact As New Contact()

With Contact

.ContactId = reader("ContactID")

.FirstName = reader("FirstName")

.LastName = reader("LastName")

.Email = reader("EmailAddress")

End With

Context.Post(OnContactRetreivedCallBack, Contact)

End While

Context.Post(OnOperationCompletedCallBack, Nothing)

Catch ex As ThreadAbortException

If reader IsNot Nothing Then

cmd.Cancel()

End If

Context.Post(OnOperationCompletedCallBack, New
OperationCanceledException("La carga de los contactos ha sido cancelada"))

Catch ex As Exception

Context.Post(OnOperationCompletedCallBack, ex)

Finally

If reader IsNot Nothing Then

reader.Close()

End If

If cn IsNot Nothing AndAlso cn.State <> ConnectionState.Closed
Then

cn.Close()

End If

End Try

End Sub



Public Function GetContactsCount() As Integer

Dim cn As New SqlClient.SqlConnection("Data
Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks")

Dim cmd As New SqlClient.SqlCommand("select count(*) from
Person.Contact", cn)

Try

cn.Open()

Return cmd.ExecuteScalar()

Finally

If cn.State <> ConnectionState.Closed Then cn.Close()

End Try

End Function





Private Sub OnContactRetreived(ByVal Contact As Object)

Dim e As New ContactRetreivedEventArgs(Contact)

RaiseEvent ContactRetreived(Me, e)

End Sub



Private Sub OnOperationCompleted(ByVal Exception As Object)

Dim e As New OperationCompletedEventArgs(Exception)

RaiseEvent OperationCompleted(Me, e)

End Sub



End Class



Que lo disfrutes :-)

Jesús López
MVP
Respuesta Responder a este mensaje
#2 Ch0rY
05/01/2006 - 15:58 | Informe spam
Muchas, pero q muchas gracias por el analisis, por lo menos ya se que aunque
"funcione", no lo hace como yo creia, lo cual significa, q tendre q
replantearlo por entero.

Lo de los cuatro botones, es para ir haciendo q se ejecutase un hilo, luego
otro, pa ver si funcionaba, q no funcionaba, ya ta has dao cuenta.

El ejemplo, lo estudiare despues de

(1) Leer mas la documentación
(2) Leer mas la documentación
(3) Leer mas la documentación

si me entero de algo, claro.

De momento voy a imprimir el mensaje q mas mandao, para no perderlo, como he
hecho con muchos otros mensajes q solo los grabe en .txt y cuando he tenido
de formatear el disco, no me he acordao de grabarlos.

Muschas gracias de nuevo, y al tema

Chory
Respuesta Responder a este mensaje
#3 Ch0rY
17/01/2006 - 13:42 | Informe spam
Bueeeeno, creo q ya he conseguido q funcione en un thread independiente,
falta por hacer mucho para q funcione al 100%, pero algo es algo.


Codigo
' En un formulario

Imports (aplicacion).Currantes

Dim WithEvents Bajar As New Curra
Private Sub btn_Descargar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btn_Descargar.Click

With Bajar
.Ruta = (La Ruta de descarga)
.CarpetaDestino = txt_Carpeta.Text
.Cookie = (la Cookie)
End With
end sub

' Una clase
Imports System.IO
Imports System.Threading
Imports System.Net
Namespace Currantes
Public Class Curra
Public Event Hecho(ByVal LlevoHecho As Long, ByVal Tamanio As Long)
Public Event FicheroEncontrado(ByVal Fichero As String, ByVal Desde
As String)

Private _Hilo As Thread = Nothing

Public Sub New()
_Hilo = New Thread(New ThreadStart(AddressOf Haz))
End Sub
Public Sub Start()
_Hilo.Start()
End Sub

Private _Ruta As String
Public Property Ruta() As String
Get
Return _Ruta
End Get
Set(ByVal value As String)
_Ruta = value
End Set
End Property
Private _Fichero As String = Nothing
Public Property Fichero() As String
Get
Return _Fichero
End Get
Set(ByVal value As String)
_Fichero = value
End Set
End Property
Private _CarpetaDestino As String
Public Property CarpetaDestino() As String
Get
Return _CarpetaDestino
End Get
Set(ByVal value As String)
_CarpetaDestino = value
End Set
End Property
Private _Cookie As String = Nothing
Public Property Cookie() As String
Get
Return _Cookie
End Get
Set(ByVal value As String)
_Cookie = value
End Set
End Property

Public Sub BuscaMapa(ByVal Enlace As String)
Dim request As WebRequest = WebRequest.Create(Enlace)
request.Method = "HEAD"
If Not IsNothing(_Cookie) Then
request.Headers.Add("Cookie", _Cookie)
End If
Dim response As WebResponse = request.GetResponse()
Try
_Ruta = response.ResponseUri.AbsoluteUri
Dim a() As String = Ruta.Split("/")
_Fichero = a(UBound(a))
RaiseEvent FicheroEncontrado(_Fichero, _Ruta)
Catch ex As WebException

Catch ex As Exception

End Try
response.Close()
If Not IsNothing(_Fichero) Then
DescargaFichero()
End If
End Sub
Private Sub DescargaFichero()
Dim u As New Uri(Ruta)
Dim req As HttpWebRequest
req = HttpWebRequest.Create(u)
req.Method = "GET"
Dim ar As IAsyncResult = req.BeginGetResponse(AddressOf
DescargarFichero2, req)
End Sub
Private Sub DescargarFichero2(ByVal ar As IAsyncResult)
Try
Dim rsp As WebResponse
Dim wrt As FileStream
Dim cbRead As Int32 = 0

rsp = CType(ar.AsyncState, HttpWebRequest).EndGetResponse
(ar)
Dim stm As Stream = rsp.GetResponseStream()
wrt = New FileStream(_CarpetaDestino & _Fichero &
".Descargando", FileMode.Create)

Dim buffer(1024) As Byte
Do
'BarraVale = wrt.Length
cbRead = stm.Read(buffer, 0, 1024)

If cbRead = 0 Then Exit Do
wrt.Write(buffer, 0, cbRead)
RaiseEvent Hecho(wrt.Length, rsp.ContentLength)
Loop
wrt.Close()
Rename(_CarpetaDestino & _Fichero & ".Descargando",
_CarpetaDestino & _Fichero)
rsp.Close()

Catch ex As Exception
If ex.Message.ToLower.IndexOf("not found") = -1 Then
MsgBox(ex.Message)
Else
' Excepcion = "Fichero no encontrado"
End If
'Descargando = False
End Try

End Sub

Private Sub Haz()
If _Fichero = Nothing Then Call BuscaMapa(_Ruta)
End Sub
End Class
End Namespace


Fin Codigo

Ahora tengo que conseguir manipular un control del formulario desde los
eventos generados por la clase

' En el Formulario

Public Sub Curra_Hecho(ByVal LlevoHecho As Long, ByVal Tamanio As Long)
Handles Bajar.Hecho
' EstadoProgreso es una barra de progreso
EstadoProgreso.Maximum = Tamanio
EstadoProgreso.Value = LlevoHecho
End Sub


Como dijo aquel sabio Ayyyn, q contento toyyyyyy
chory
Respuesta Responder a este mensaje
#4 Jesús López
17/01/2006 - 14:33 | Informe spam
No quiero que pienses que soy un aguafiestas, pero ya que has puesto el
código me gustaría decirte un par de cosillas:

(1) No tiene mucho sentido que en el método DescargarFichero hagas:

Dim ar As IAsyncResult = req.BeginGetResponse(AddressOf
DescargarFichero2, req)

En su lugar deberías llamar directamente a DescargarFichero2. La razón
por la que no tiene sentido es que "DescargarFichero" ya se está ejecutando
en segundo plano (un hilo), así que ¿para qué hacer ahora una llamada
asíncrona?. No es necesario y sólo añade complejidad al código.

(2) Cuando vayas a responder a los eventos del objeto Bajar en el
formulario, va a fallar, ya que los procedimientos de evento se van a
ejecutar en el hilo que los lanzó los eventos y no puedes actualizar el
interfaz de usuario en un hilo diferente del que creó los controles windows
(que es el hilo principal). O bien te saldrá una excepción o bien se quedará
colgada la aplicación o hará cosas raras ya que Windows Forms no es seguro
para subprocesos. Mira el código que te puse en el otro mensaje, ahí se
muestra una manera "segura" de lanzar los eventos usando
SynchronizationContext. Básicamente lo que tienes que hacer es:

a. Guardar el SynchronizationContext actual en una variable privada cuando
se llame al construtor de la clase Curra o en método Start.

b. En vez de lanzar directamente el evento en los métodos que se ejecutan en
segundo plano, llama al método Post del SynchronizationContext pasándole un
delegado que apunte al método que realmente lanza el evento, esto provocará
que el método que lanza el evento se ejecute en el hilo que estaba activo
cuando se guardo el SyncrhonizationContext. Mira el método BackgroundLoad de
la clase que te mandé. Ahí para informar del progreso hace:

Context.Post(OnContactRetreivedCallBack, Contact)

OnContactRetreivedCallBack es un delegado que apunta al método
OnContactRetreived y Contact es un contacto. En tu caso en vez de pasar un
Contact tienes que pasar un objeto con la información del evento.

c Crea métodos que simplemente lanzen los eventos. Estos métodos los
llamarás indirectamente a través del método Post de SynchronizationContext.
En el ejemplo que te escribí, tengo los métodos:

OnContactRetreived (información de progreso) que lanza el evento
ContactRetreived
OnOperationCompleted (informa de que se ha terminado la operación con o sin
error) que lanza el evento OperationCompleted

Saludos:

Jesús López
MVP




"Ch0rY" escribió en el mensaje
news:
Bueeeeno, creo q ya he conseguido q funcione en un thread independiente,
falta por hacer mucho para q funcione al 100%, pero algo es algo.


Codigo
' En un formulario

Imports (aplicacion).Currantes

Dim WithEvents Bajar As New Curra
Private Sub btn_Descargar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btn_Descargar.Click

With Bajar
.Ruta = (La Ruta de descarga)
.CarpetaDestino = txt_Carpeta.Text
.Cookie = (la Cookie)
End With
end sub

' Una clase
Imports System.IO
Imports System.Threading
Imports System.Net
Namespace Currantes
Public Class Curra
Public Event Hecho(ByVal LlevoHecho As Long, ByVal Tamanio As Long)
Public Event FicheroEncontrado(ByVal Fichero As String, ByVal Desde
As String)

Private _Hilo As Thread = Nothing

Public Sub New()
_Hilo = New Thread(New ThreadStart(AddressOf Haz))
End Sub
Public Sub Start()
_Hilo.Start()
End Sub

Private _Ruta As String
Public Property Ruta() As String
Get
Return _Ruta
End Get
Set(ByVal value As String)
_Ruta = value
End Set
End Property
Private _Fichero As String = Nothing
Public Property Fichero() As String
Get
Return _Fichero
End Get
Set(ByVal value As String)
_Fichero = value
End Set
End Property
Private _CarpetaDestino As String
Public Property CarpetaDestino() As String
Get
Return _CarpetaDestino
End Get
Set(ByVal value As String)
_CarpetaDestino = value
End Set
End Property
Private _Cookie As String = Nothing
Public Property Cookie() As String
Get
Return _Cookie
End Get
Set(ByVal value As String)
_Cookie = value
End Set
End Property

Public Sub BuscaMapa(ByVal Enlace As String)
Dim request As WebRequest = WebRequest.Create(Enlace)
request.Method = "HEAD"
If Not IsNothing(_Cookie) Then
request.Headers.Add("Cookie", _Cookie)
End If
Dim response As WebResponse = request.GetResponse()
Try
_Ruta = response.ResponseUri.AbsoluteUri
Dim a() As String = Ruta.Split("/")
_Fichero = a(UBound(a))
RaiseEvent FicheroEncontrado(_Fichero, _Ruta)
Catch ex As WebException

Catch ex As Exception

End Try
response.Close()
If Not IsNothing(_Fichero) Then
DescargaFichero()
End If
End Sub
Private Sub DescargaFichero()
Dim u As New Uri(Ruta)
Dim req As HttpWebRequest
req = HttpWebRequest.Create(u)
req.Method = "GET"
Dim ar As IAsyncResult = req.BeginGetResponse(AddressOf
DescargarFichero2, req)
End Sub
Private Sub DescargarFichero2(ByVal ar As IAsyncResult)
Try
Dim rsp As WebResponse
Dim wrt As FileStream
Dim cbRead As Int32 = 0

rsp = CType(ar.AsyncState, HttpWebRequest).EndGetResponse
(ar)
Dim stm As Stream = rsp.GetResponseStream()
wrt = New FileStream(_CarpetaDestino & _Fichero &
".Descargando", FileMode.Create)

Dim buffer(1024) As Byte
Do
'BarraVale = wrt.Length
cbRead = stm.Read(buffer, 0, 1024)

If cbRead = 0 Then Exit Do
wrt.Write(buffer, 0, cbRead)
RaiseEvent Hecho(wrt.Length, rsp.ContentLength)
Loop
wrt.Close()
Rename(_CarpetaDestino & _Fichero & ".Descargando",
_CarpetaDestino & _Fichero)
rsp.Close()

Catch ex As Exception
If ex.Message.ToLower.IndexOf("not found") = -1 Then
MsgBox(ex.Message)
Else
' Excepcion = "Fichero no encontrado"
End If
'Descargando = False
End Try

End Sub

Private Sub Haz()
If _Fichero = Nothing Then Call BuscaMapa(_Ruta)
End Sub
End Class
End Namespace


Fin Codigo

Ahora tengo que conseguir manipular un control del formulario desde los
eventos generados por la clase

' En el Formulario

Public Sub Curra_Hecho(ByVal LlevoHecho As Long, ByVal Tamanio As Long)
Handles Bajar.Hecho
' EstadoProgreso es una barra de progreso
EstadoProgreso.Maximum = Tamanio
EstadoProgreso.Value = LlevoHecho
End Sub


Como dijo aquel sabio Ayyyn, q contento toyyyyyy
chory
Respuesta Responder a este mensaje
#5 Ch0rY
17/01/2006 - 15:14 | Informe spam
De aguafiestas nada, demasiao q te molestas en mirar, explicar,
comentar, sugerir, enseñar,..., estaria bueno.

A volver a leer y estudiar el codigo q me mandaste y el nuevo q has
puesto.

Gracias de nuevo
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida