Estoy creando un aplicacion que busca palabras en un archivo de texto
El problema viene cuando intento usar archivo un poco mas grande la aplicacion se queda congelada, sin poder hacer nada.
Para solucionarlo simplemmente ejecuta las órdenes de manera asíncrona en el mismo thread de la UI, o en un thread separado.
Este ejemplo toma un archivo de texto de 300 MB, busca 3 palabras y muestra la suma de coincidencias de las palabras encontradas.
Imports System.Threading.Tasks
Public NotInheritable Class Form1 : Inherits Form
Private Sub Button1_Click(sender As Object, e As EventArgs) _
Handles Button1.Click
Dim ocurrences As Integer = -1
Task.Factory.StartNew(Sub() Me.Find("C:\resumen.txt", {"Solucion", "Libro", "Autor"}, ocurrences)).
ContinueWith(Sub()
Me.Invoke(Sub()
TextBox1.Text = String.Format("Coincidencias: {0}", CStr(ocurrences))
Label1.Text = "Operación completada!"
End Sub)
End Sub)
Dim sw As New Stopwatch
sw.Start()
Do Until (ocurrences <> -1)
Label1.Text = String.Format("{0} segundos...", sw.Elapsed.TotalSeconds.ToString("n2"))
Application.DoEvents()
Loop
sw.Reset()
End Sub
Private Sub Find(ByVal textFilepath As String,
ByVal values As IEnumerable(Of String),
ByRef var As Integer)
Using sr As New StreamReader(textFilepath, True)
var = (From word As String In (sr.ReadToEnd.Split).AsParallel
Select (From value As String In values
Where word.Equals(value, StringComparison.OrdinalIgnoreCase)).Count
).Sum
End Using
End Sub
End Class
El contador de segundos lo he colocado solo para que denotes que no se congela la UI, pero en realidad eso vuelve (algo)más lento el procedimiento xD.
He usado LINQ por su intuitiva y simplificada sintaxis, pero si quieres mayor optimización en respecto al rendimiento entonces usa un For. Aquí tienes varios ejemplos en C#:
➢
C# .Net: Fastest Way to check if a string occurs within a string
Backgroundworker y Threads
Me podrian decir cual es la diferencia entre ambos
_____________________________________________________________________
EDITO: Ups, he ido a revisar mi comentario y no se por qué leí que preguntabas sobre "
Tasks" en lugar de "
Threads", me he dado cuenta tarde así que todo esto que comento aquí abajo es sobre la class
Task y no sobre theads o hilos en general, pero de todas formas es lo que deberías utilizar, una Task.
Sobre las diferencias, la class
Threading.Thread es el concepto o implementación low-level de un hilo, mientras que la class
Threading.Thread sería un nivel superior de su implementación, ya que tiene mayor abstracción.
La class
Threading.Task representa una operación asíncrona que es llevada acabo mediente hilos, los cuales son administrados mediante su propio planificador de hilos o
thread scheduler.
No te conviene usar hilos tradicionales mediante
Threading.Thread ya que está pensado para otros escenarios donde se requiere un mayor requisito de computación, es preferible que uses la class
Threading.Task.
_____________________________________________________________________
La diferencia más grande tal vez está en su modo de empleo, ya que la class
Task es la evolución de la class
BackgroundWorker.
Existen muchas diferencias internas entre si en el contexto de como administra los hilos, su cancelación, la sincronia de código, etc. Para destacar todo ello habría que escribir un libro, así que si quieres aprender en profundidad sobre sus diferencias es mejor que busques en Google artículos que hablen sobre ello, pero en resumen el BackgroundWorker o BGW tiene varios problemas de diseño, y de por si es muy tedioso utilizarlo al estar basado u orientado en eventos; también tiene problemas de sincronización y de tokens de cancelación. Con el paso de los años es posible que Microsoft marque "deprecada" dicha class.
Te muestro una simple comparación de uso:
BGW:
Dim WithEvents bgw As New BackgroundWorker
Private Sub Bgw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
Handles bgw.DoWork
Thread.Sleep(1000)
End Sub
Private Sub Bgw_RunWorkerCompleted(ByVal sender As Object,ByVal e As RunWorkerCompletedEventArgs) _
Handles bgw.RunWorkerCompleted
MessageBox.Show("Operation completed!")
End Sub
Private Sub RunBgw()
Me.bgw.RunWorkerAsync()
End Sub
BGW simplificado:
Sub ...
Using bgw As New BackgroundWorker
AddHandler bgw.DoWork, Sub()
Thread.Sleep(1000)
End Sub
AddHandler bgw.RunWorkerCompleted, Sub()
MessageBox.Show("Operation completed!")
End Sub
bgw.RunWorkerAsync()
End Using
End sub
Task.Run:
Async Sub ...
Await Task.Run(Sub()
Thread.Sleep(1000)
End Sub)
MessageBox.Show("Operation completed!")
End sub
Nota: Async/Await forman parte de .NetFx 4.5
Saludos!