Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: Eleкtro en 29 Noviembre 2012, 19:36 pm



Título: Mi form se cuelga al iniciar un thread...
Publicado por: Eleкtro en 29 Noviembre 2012, 19:36 pm
Para los que no lo sepan, estoy diseñando un programa, y tenía un problema, la app se colgaba al darle al botón "start", hasta que "el proceso" finalizaba no podía tocar nada.
...
...
Después de estar días para conseguir meter una función en un thread separado, ahora que lo he conseguido ...no hay ninguna diferencia... hasta que no finaliza "el proceso" no puedo mover el form por la pantalla, ni pulsar cualquier botón del form, ni nada, solo puedo esperar hasta que acabe...

...Espero alguna ayuda, porqué yo ya no sé que más intentar para que no se me cuelgue, no sé lo que he hecho mal.

(http://img853.imageshack.us/img853/2071/prtscrcapturegq.jpg)

Hasta que no se terminan de mostrar todas las líneas del richtextbox no me deja tocar NADA.

...Muchas gracias por leer.




El form:

Código
  1. Imports System.IO
  2. Imports System.Threading
  3. Imports System.Runtime.InteropServices
  4. Imports System.ComponentModel
  5. Imports Ookii.Dialogs
  6.  
  7. Public Class Form1
  8.  
  9. #Region "Declarations"
  10.  
  11.    ' MediaInfo
  12.    Dim MI As MediaInfo
  13.  
  14.    ' Others
  15.    Dim NameOfDirectory As String = Nothing
  16.    Dim aFile As FileInfo
  17.  
  18. #End Region
  19.  
  20. #Region "Properties"
  21. #End Region
  22.  
  23. #Region "Load / Close"
  24.  
  25.    ' Load
  26.    Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  27.  
  28.        ' MediaInfo Instance
  29.        MI = New MediaInfo
  30.  
  31.    End Sub
  32.  
  33. #End Region
  34.  
  35. #Region "Get Total files Function"
  36. #End Region
  37.  
  38. #Region "Option checkboxes"
  39. #End Region
  40.  
  41. #Region "Folder buttons"
  42. #End Region
  43.  
  44.  
  45. #Region "Append text function"
  46.  
  47.    ' Append Text
  48.    Public Sub AppendText(box As RichTextBox, color As Color, text As String)
  49.  
  50.        Control.CheckForIllegalCrossThreadCalls = False
  51.  
  52.        Dim start As Integer = box.TextLength
  53.        box.AppendText(text)
  54.        Dim [end] As Integer = box.TextLength
  55.  
  56.        ' Textbox may transform chars, so (end-start) != text.Length
  57.        box.[Select](start, [end] - start)
  58.        If True Then
  59.            box.SelectionColor = color
  60.            ' could set box.SelectionBackColor, box.SelectionFont too.
  61.        End If
  62.        box.SelectionLength = 0
  63.        ' clear
  64.    End Sub
  65.  
  66. #End Region
  67.  
  68.  
  69. #Region "Thread"
  70.  
  71.    Public _WaitHandle_FirstThreadDone As New System.Threading.AutoResetEvent(False)
  72.  
  73.    Public Sub ThreadProc(ByVal aDir As DirectoryInfo)
  74.  
  75.        Dim aFile As FileInfo
  76.  
  77.        For Each aFile In aDir.GetFiles()
  78.  
  79.            If accepted_extensions.ToLower.Contains(aFile.Extension.ToLower) Then
  80.  
  81.                ' print output
  82.                AppendText(consolebox, Color.Yellow, "Processing: ")
  83.                AppendText(consolebox, Color.White, aFile.ToString() + vbNewLine)
  84.                consolebox.ScrollToCaret()
  85.                processedfiles += 1
  86.                totalfiles_label.Text = "Processed " + processedfiles.ToString() + " of " + totalfiles.ToString() + " total video files"
  87.  
  88.                ' Attributes
  89.                If attribs = True Then
  90.                    aFile.Attributes = (aFile.Attributes And Not FileAttributes.ReadOnly And Not FileAttributes.Hidden And Not FileAttributes.System And Not FileAttributes.Archive)
  91.                End If
  92.  
  93.                ' Rename to Word-Case
  94.                If wordcase = True Then
  95.                    Dim renamestr As String = StrConv(aFile.Name, VbStrConv.ProperCase)
  96.                    My.Computer.FileSystem.RenameFile(aFile.FullName, renamestr + "_FILMEN")
  97.                    My.Computer.FileSystem.RenameFile(aFile.FullName + "_FILMEN", renamestr)
  98.                End If
  99.  
  100.                ' Rename to Lower-Case
  101.                If lowercase = True Then
  102.                    Dim renamestr As String = StrConv(aFile.Name, VbStrConv.Lowercase)
  103.                    My.Computer.FileSystem.RenameFile(aFile.FullName, renamestr + "_FILMEN")
  104.                    My.Computer.FileSystem.RenameFile(aFile.FullName + "_FILMEN", renamestr)
  105.                End If
  106.  
  107.                ' Playlists
  108.                If playlist = True Then
  109.                    Using writer As StreamWriter = New StreamWriter(aFile.DirectoryName.ToString() & "\" & aDir.Name & ".m3u", True, System.Text.Encoding.UTF8)
  110.                        writer.WriteLine(aFile.FullName.ToString())
  111.                    End Using
  112.                End If
  113.  
  114.                ' MEDIAINFO:  (ac3, dts, wav and multitrack)
  115.                If ac3 = True Or dts = True Or wav = True Or multitrack = True Then
  116.  
  117.                    MI.Open(aFile.FullName)
  118.  
  119.                    Dim Pos As Integer = 0
  120.                    To_Display = Nothing
  121.  
  122.                    ' multitrack
  123.                    If multitrack = True Then
  124.                        If MI.Count_Get(StreamKind.Audio) > 1 Then
  125.                            results_box.AppendText("Multi Track: " + aFile.FullName.ToString() + vbNewLine)
  126.                            results_box.SelectionStart = results_box.Text.Length
  127.                            results_box.ScrollToCaret()
  128.                            problems += 1
  129.                            problems_label.Text = problems.ToString() + " problems found"
  130.                        End If
  131.                    End If
  132.  
  133.                    While Pos < MI.Count_Get(StreamKind.Audio)
  134.  
  135.                        ' AC-3
  136.                        If ac3 = True Then
  137.                            If MI.Get_(StreamKind.Audio, Pos, "Format").ToString() = "AC-3" Then
  138.                                results_box.AppendText("AC3 Track: " + aFile.FullName.ToString() + vbNewLine)
  139.                                results_box.SelectionStart = results_box.Text.Length
  140.                                results_box.ScrollToCaret()
  141.                                problems += 1
  142.                                problems_label.Text = problems.ToString() + " problems found"
  143.                            End If
  144.                        End If
  145.  
  146.                        ' DTS
  147.                        If dts = True Then
  148.                            If MI.Get_(StreamKind.Audio, Pos, "Format").Contains("DTS") Then
  149.                                results_box.AppendText("DTS Track: " + aFile.FullName.ToString() + vbNewLine)
  150.                                results_box.SelectionStart = results_box.Text.Length
  151.                                results_box.ScrollToCaret()
  152.                                problems += 1
  153.                                problems_label.Text = problems.ToString() + " problems found"
  154.                            End If
  155.                        End If
  156.  
  157.                        ' WAV
  158.                        If wav = True Then
  159.                            If MI.Get_(StreamKind.Audio, Pos, "Format").Contains("PCM") Then
  160.                                results_box.AppendText("WAV Track: " + aFile.FullName.ToString() + vbNewLine)
  161.                                results_box.SelectionStart = results_box.Text.Length
  162.                                results_box.ScrollToCaret()
  163.                                problems += 1
  164.                                problems_label.Text = problems.ToString() + " problems found"
  165.                            End If
  166.                        End If
  167.  
  168.                        System.Math.Max(System.Threading.Interlocked.Increment(Pos), Pos - 1)
  169.                    End While
  170.                End If
  171.  
  172.                If metadata = True Then
  173.                    Dim ffmpeg_process As New Process()
  174.                    Dim ffmpeg_startinfo As New ProcessStartInfo()
  175.                    ffmpeg_startinfo.FileName = "cmd.exe "
  176.                    ffmpeg_startinfo.Arguments = "/C ffmpeg.exe -y -i " & ControlChars.Quote & aFile.FullName.ToString() & ControlChars.Quote & " -f ffmetadata " & ControlChars.Quote & "%TEMP%\" & aFile.Name.ToString() & "_metadata.txt" & ControlChars.Quote & " >NUL 2>&1 && Type " & ControlChars.Quote & "%TEMP%\" & aFile.Name.ToString() & "_metadata.txt" & ControlChars.Quote & "| FINDSTR /I " & ControlChars.Quote & "^INAM ^title" & ControlChars.Quote & " >NUL && Echo FOUND && EXIT || Echo NOT FOUND && Exit"
  177.                    ffmpeg_startinfo.UseShellExecute = False
  178.                    ffmpeg_startinfo.CreateNoWindow = True
  179.                    ffmpeg_startinfo.RedirectStandardOutput = True
  180.                    ffmpeg_startinfo.RedirectStandardError = True
  181.                    ffmpeg_process.EnableRaisingEvents = True
  182.                    ffmpeg_process.StartInfo = ffmpeg_startinfo
  183.                    ffmpeg_process.Start()
  184.                    ffmpeg_process.WaitForExit()
  185.  
  186.                    Dim readerStdOut As IO.StreamReader = ffmpeg_process.StandardOutput
  187.                    Dim FINDstdOut As String = ffmpeg_process.StandardOutput.ReadToEnd
  188.  
  189.                    If FINDstdOut.Contains("FOUND") Then
  190.                        AppendText(consolebox, Color.Red, "TAGS FOUND! Removing tags, please wait..." & vbNewLine)
  191.                        Dim relative_dir As String = aDir.FullName.ToString().Replace(aDir.Root.ToString(), "\")
  192.                        Dim ffmpegconvert_process As New Process()
  193.                        Dim ffmpegconvert_startinfo As New ProcessStartInfo()
  194.                        ffmpegconvert_startinfo.FileName = "cmd.exe "
  195.                        ffmpegconvert_startinfo.Arguments = "/C MKDIR " & ControlChars.Quote & userSelectedFolderPathmetadata & relative_dir & ControlChars.Quote & " 2>NUL & ffmpeg.exe -y -i " & ControlChars.Quote & aFile.FullName.ToString() & ControlChars.Quote & " -c copy -map_metadata -1 " & ControlChars.Quote & userSelectedFolderPathmetadata & relative_dir & "\" & aFile.Name.ToString() & ControlChars.Quote & " >NUL 2>&1 & Exit"
  196.                        ffmpegconvert_startinfo.UseShellExecute = False
  197.                        ffmpegconvert_startinfo.CreateNoWindow = True
  198.                        ffmpegconvert_startinfo.RedirectStandardOutput = True
  199.                        ffmpegconvert_startinfo.RedirectStandardError = True
  200.                        ffmpegconvert_process.EnableRaisingEvents = True
  201.                        ffmpegconvert_process.StartInfo = ffmpegconvert_startinfo
  202.                        ffmpegconvert_process.Start()
  203.                        ffmpegconvert_process.WaitForExit()
  204.                        'Dim ffmpegconvertreaderStdOut As IO.StreamReader = ffmpegconvert_process.StandardOutput
  205.                    End If
  206.  
  207.                    Do While readerStdOut.EndOfStream = False
  208.                        consolebox.AppendText(readerStdOut.ReadLine() + vbNewLine)
  209.                        consolebox.SelectionStart = consolebox.Text.Length
  210.                        consolebox.ScrollToCaret()
  211.                    Loop
  212.  
  213.                End If
  214.            End If
  215.        Next
  216.  
  217.        _WaitHandle_FirstThreadDone.Set()
  218.    End Sub
  219.  
  220.  
  221. #End Region
  222.  
  223.  
  224. #Region "Organize function"
  225.  
  226.    Public Sub MediaInfo(Directory)
  227.        Dim MyDirectory As DirectoryInfo
  228.        MyDirectory = New DirectoryInfo(NameOfDirectory)
  229.        MediaInfoWorkWithDirectory(MyDirectory)
  230.    End Sub
  231.  
  232.    Public Sub MediaInfoWorkWithDirectory(ByVal aDir As DirectoryInfo)
  233.        Dim nextDir As DirectoryInfo
  234.        Dim t As New Threading.Thread(AddressOf ThreadProc)
  235.        t.Start(aDir)
  236.        _WaitHandle_FirstThreadDone.WaitOne()
  237.        For Each nextDir In aDir.GetDirectories
  238.            If playlist = True Then
  239.                Using writer As StreamWriter = New StreamWriter(aDir.FullName & "\" & nextDir.Name & "\" & nextDir.Name & ".m3u", False, System.Text.Encoding.UTF8)
  240.                    'overwrite existing playlist
  241.                End Using
  242.            End If
  243.            MediaInfoWorkWithDirectory(nextDir)
  244.        Next
  245.    End Sub
  246.  
  247. #End Region
  248.  
  249.  
  250. #Region "Action buttons"
  251.  
  252.    ' start button
  253.    Public Sub Button2_Click(sender As Object, e As EventArgs) Handles start_button.Click
  254.  
  255.        If metadata = True And metadatatextbox.Text = "Select a folder to save the converted videos without metadata..." Then
  256.            MsgBox("You must select a folder for the saved metadata videos...", , "Filmen v1.0")
  257.        Else
  258.            If ac3 = False And dts = False And wav = False And multitrack = False And playlist = False And attribs = False And wordcase = False And metadata = False And lowercase = False Then
  259.                MsgBox("You must select at least one option...", , "Filmen v1.0")
  260.            Else
  261.  
  262.                consolebox.Clear()
  263.  
  264.                ' pause / cancel button ON
  265.                pause_button.Enabled = True
  266.                cancel_button.Enabled = True
  267.  
  268.                ' Total files label
  269.                processedfiles = 0
  270.                totalfiles_label.Text = totalfiles.ToString() + " Total video files"
  271.  
  272.                ' Problems label
  273.                problems = 0
  274.                problems_label.Text = "0 problems found"
  275.  
  276.                ' Organization process
  277.                NameOfDirectory = userSelectedFolderPath
  278.                MediaInfo(NameOfDirectory)
  279.                consolebox.AppendText(vbNewLine + "[+] Organization finalized!" + vbNewLine)
  280.                consolebox.Refresh()
  281.                consolebox.SelectionStart = consolebox.Text.Length
  282.                consolebox.ScrollToCaret()
  283.  
  284.                ' pause / cancel button OFF
  285.                pause_button.Enabled = False
  286.                cancel_button.Enabled = False
  287.  
  288.            End If
  289.        End If
  290.    End Sub
  291.  
  292. #End Region
  293.  
  294. End Class
  295.  


Título: Re: Mi form se cuelga al iniciar un thread...
Publicado por: seba123neo en 29 Noviembre 2012, 21:39 pm
vi tanto temas tuyos de thread, que te hice este ejemplo simple, para que veas que facil es hacer un thread, de un proceso largo que te traba toda la UI.

Código
  1. Imports System.Threading
  2.  
  3. Public Class Form1
  4.  
  5.    Private Delegate Sub Progreso()
  6.    Private vHilo As Thread
  7.  
  8.    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  9.  
  10.        TextBox1.Text = 0
  11.  
  12.        vHilo = New Thread(New ThreadStart(AddressOf Proceso))
  13.        vHilo.Start()
  14.    End Sub
  15.  
  16.    Private Sub Proceso()
  17.        If Me.InvokeRequired Then
  18.            Me.Invoke(New Progreso(AddressOf Proceso))
  19.        Else
  20.            Do While True
  21.                TextBox1.Text += CInt(1)
  22.                Application.DoEvents()
  23.            Loop
  24.        End If
  25.    End Sub
  26. End Class

lo que hace es simplemente sumar un valor en el textbox en un bucle infinito, que sin esto se te trabaria toda la pantalla y no podrias tocar nada, y como usa el control textbox hay que usar un delgado, de lo contrario te sale el famoso error "Operación no válida a través de subprocesos: Se tuvo acceso al control 'TextBox1' desde un subproceso distinto a aquel en que lo creó.", ese error quiere decir que no podes manipular un control del formulario, ya que este esta en un hilo diferente (el hilo de la UI), que es diferente al hilo que creas vos ahi.

con esa forma podes hacer lo que se te cante.

saludos.


Título: Re: Mi form se cuelga al iniciar un thread...
Publicado por: kub0x en 29 Noviembre 2012, 21:48 pm
y como usa el control textbox hay que usar un delgado, de lo contrario te sale el famoso error "Operación no válida a través de subprocesos: Se tuvo acceso al control 'TextBox1' desde un subproceso distinto a aquel en que lo creó.", ese error quiere decir que no podes manipular un control del formulario, ya que este esta en un hilo diferente (el hilo de la UI), que es diferente al hilo que creas vos ahi.

Como dato, si no quieres emplear delegados en el code, en el contexto de insertar una modificación en un control dentro de un subproceso distinto al que creo dicho control, simplemente se "fixea" el error seteando la propiedad CheckForIllegalCrossThreadCalls a False. De esta manera evitas que se compruebe que un la propiedad de un control fue modificada desde un subproceso distinto al original.

Más info el la Msdn, dónde explican como utilizar dicha propiedad y su funcionamiento -> http://msdn.microsoft.com/es-es/library/system.windows.forms.control.checkforillegalcrossthreadcalls.aspx (http://msdn.microsoft.com/es-es/library/system.windows.forms.control.checkforillegalcrossthreadcalls.aspx)

Saludos!


Título: Re: Mi form se cuelga al iniciar un thread...
Publicado por: seba123neo en 29 Noviembre 2012, 22:06 pm
si, pero esa propiedad no es recomendada usar.


Título: Re: Mi form se cuelga al iniciar un thread...
Publicado por: Keyen Night en 29 Noviembre 2012, 22:42 pm
Hay casos en los cuales no funciona, siempre es de mejor practica usar delegados, aunque si es algo muy sencillo se puede usar pero igual no se recomienda.


Título: Re: Mi form se cuelga al iniciar un thread...
Publicado por: spiritdead en 30 Noviembre 2012, 07:00 am
Como dato, si no quieres emplear delegados en el code, en el contexto de insertar una modificación en un control dentro de un subproceso distinto al que creo dicho control, simplemente se "fixea" el error seteando la propiedad CheckForIllegalCrossThreadCalls a False. De esta manera evitas que se compruebe que un la propiedad de un control fue modificada desde un subproceso distinto al original.

Más info el la Msdn, dónde explican como utilizar dicha propiedad y su funcionamiento -> http://msdn.microsoft.com/es-es/library/system.windows.forms.control.checkforillegalcrossthreadcalls.aspx (http://msdn.microsoft.com/es-es/library/system.windows.forms.control.checkforillegalcrossthreadcalls.aspx)

Saludos!
q aprenda a usar delegados, es lo mas maravilloso que puede existir en cuanto al tema de multi-hilos :D

por cierto EleKtro H@cker
tenes los 2 foros (este y el-hacker) spameados de consultas, no seria mejor investigar ? y hacer preguntas mas precisas :/