Duda con BackgroundWorker ?

Iniciado por TrashAmbishion, 15 Septiembre 2016, 17:30 PM

0 Miembros y 1 Visitante están viendo este tema.

TrashAmbishion

Hola,

Que podria suceder para que una BW no se detuviera, le estoy dando la orden de cancelar y en el evento que se dispara cuando finaliza puse una variable publica que la voy comprobando con un while hasta que se haga true para poder continuar, llega bien hasta el Mywork.CancelAsync pero no se dispara el evento de que finalizo, verifique y tampoco sigue trabajando verificando ninguna de las funciones que tiene, cuando lo inicializo declaro que puede detenerse.

Es que necesito agregar a un array valores y en ese BW hay una funcion que cada cierto tiempo la usa para hacer comprobaciones.

Leyendo di con una funciona SymLock pero trate de usarla y me dio el mismo mensaje de que la coleccion ha sido modificada.

Edito: Podria ser que cuando hago el cancel no miro primero si esta ocupado (busy). ?

ivancea96

No entendí muy bien. Cuando llamas a CancelAsync, estableces el miembro CancellationPending a true. Dentro del código del worker, deberás comprobar la variable.

https://msdn.microsoft.com/es-es/library/system.componentmodel.backgroundworker.cancelasync(v=vs.110).aspx

TrashAmbishion

Código (vbnet) [Seleccionar]
Imports System.IO
Imports System.Management
Imports System.Text
Imports System.Threading

Public Class BWorkerProc

    ''' <summary>
    ''' The BackgroundWorker object.
    ''' </summary>
    Private WithEvents MyWorker As New ComponentModel.BackgroundWorker

    ''' <summary>
    ''' ManualResetEvent object to pause/resume the BackgroundWorker.
    ''' </summary>
    Private _busy As New ManualResetEvent(True)

    Public Property StopState As Boolean

    ''' <summary>
    ''' 'Flag para enviar los procesos
    ''' </summary>
    ''' <returns></returns>
    Public Property SendProc As Boolean

    ''' <summary>
    ''' This will start the BackgroundWorker.
    ''' </summary>
    Public Sub StartBackgroundTask()

        StopState = False

        MyWorker.WorkerSupportsCancellation = True
        MyWorker.RunWorkerAsync()

    End Sub

    ''' <summary>
    ''' This is the work to do on background.
    ''' </summary>
    Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles MyWorker.DoWork

        Do Until MyWorker.CancellationPending

            'Check weird process
            GetProccesPath()

            'Send Process
            SendProcess()

        Loop

        e.Cancel = True

    End Sub

    ''' <summary>
    ''' This happens when the BackgroundWorker is completed.
    ''' </summary>
    Private Sub MyWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
    Handles MyWorker.RunWorkerCompleted

        If e.Cancelled = True Then
            'MsgBox("Thread cancelled")
            StopState = True
        ElseIf e.Error IsNot Nothing Then
            'MsgBox("Thread error")

        Else
            'MsgBox("Thread Done!")

        End If

    End Sub

    ''' <summary>
    ''' This will pause the BackgroundWorker.
    ''' </summary>
    Public Sub Pause()

        If MyWorker.IsBusy Then
            _busy.Reset()
            'MsgBox("Thread Paused!")
        End If

    End Sub

    ''' <summary>
    ''' This will resume the BackgroundWorker.
    ''' </summary>
    Public Sub [Resume]()
        _busy.[Set]()
        'MsgBox("Thread Resumed!")
    End Sub

    ''' <summary>
    ''' This will cancel the BackgroundWorker.
    ''' </summary>
    Public Sub Cancel()
        _busy.[Set]() ' Resume worker if it is paused.
        MyWorker.CancelAsync() ' Cancel it.
    End Sub

   
End Class



El cancela el worker pero no se activa el RunWorkerComplete nunca...

Eleкtro

#3
Si no proporcionas más información no creo que te podamos ayudar por que no hay ningún código que poder analizar para verificar donde está el fallo.




Cita de: TrashAmbishion en 16 Septiembre 2016, 04:44 AMEl cancela el worker pero no se activa el RunWorkerComplete nunca...

¿Como que no?, por supuesto que si.

Toma esa class que has publicado y testeala de esta forma tan simple:

Código (vbnet) [Seleccionar]
Public Class Form1 : Inherits Form

   Private ReadOnly worker As New BWorkerProc

   Private Sub Button_Start_Click() Handles Button1.Click
       Me.worker.StartBackgroundTask()
   End Sub

   Private Sub Button_Stop_Click() Handles Button2.Click
       Me.worker.Cancel()
   End Sub

End Class


...teniendo así esta parte del código que has publicado:
Código (vbnet) [Seleccionar]
....
Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles MyWorker.DoWork

   Do Until MyWorker.CancellationPending
       Continue Do
   Loop

   e.Cancel = True

End Sub

Private Sub MyWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles myWorker.RunWorkerCompleted

   If e.Cancelled = True Then
       MsgBox("Thread cancelled")
   End If

End Sub
....




Como ves, el evento RunWorkerCompleted se dispara correctamente.






De todas formas, te recomiendo que utilices esta implementación actualizada y optimizada que escribí:

Código (vbnet) [Seleccionar]
#Region " Option Statements "

Option Strict On
Option Explicit On
Option Infer Off

#End Region

#Region " Imports "

Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Threading

#End Region

#Region " BackgroundWorker State "

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Specifies the state of a <see cref="BackgroundWorker"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public Enum BackgroundWorkerState As Integer

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is stopped.
   ''' </summary>
   Stopped = 0

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is running.
   ''' </summary>
   Running = 1

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is paused.
   ''' </summary>
   Paused = 2

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is pending on a cancellation.
   ''' </summary>
   CancellationPending = 3

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is completed (stopped).
   ''' </summary>
   Completed = 4

End Enum

#End Region

#Region " My Background Work "

Public NotInheritable Class MyBackgroundWork : Implements IDisposable

#Region " Private Fields "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' The underliying <see cref="BackgroundWorker"/> instance that runs this work on background.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <EditorBrowsable(EditorBrowsableState.Never)>
   Friend WithEvents Worker As BackgroundWorker

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' A <see cref="ManualResetEvent"/> that serves to handle synchronous operations (Run, Pause, Resume, Cancel).
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private ReadOnly mreSync As ManualResetEvent

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' A <see cref="ManualResetEvent"/> that serves to handle asynchronous operations (RunAsync, CancelAsync).
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private ReadOnly mreAsync As ManualResetEvent

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Indicates whether <see cref="BackGroundworker"/> has been initiated in synchronous mode.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isRunSync As Boolean = False

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Indicates whether a synchronous cancellation operation is requested.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isCancelSyncRequested As Boolean = False

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Indicates whether a pause operation is requested.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isPauseRequested As Boolean = False

#End Region

#Region " Properties "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Gets the current state of the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <value>
   ''' The current state of the background work.
   ''' </value>
   ''' ----------------------------------------------------------------------------------------------------
   Public ReadOnly Property State As BackgroundWorkerState
       <DebuggerStepThrough>
       Get
           Return Me.stateB
       End Get
   End Property
   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' ( Backing Field )
   ''' The current state of the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private stateB As BackgroundWorkerState = BackgroundWorkerState.Stopped

#End Region

#Region " Constructors "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Initializes a new instance of the <see cref="MyBackgroundWork"/> class.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerNonUserCode>
   Public Sub New()

       Me.Worker = New BackgroundWorker()
       Me.mreSync = New ManualResetEvent(initialState:=False)
       Me.mreAsync = New ManualResetEvent(initialState:=True)

   End Sub

#End Region

#Region " Public Methods "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Run the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to run the BackgroundWorker instance it must be stopped or completed.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub Run()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Stopped, BackgroundWorkerState.Completed
                   Me.isRunSync = True
                   With Me.Worker
                       .WorkerSupportsCancellation = False
                       .WorkerReportsProgress = False
                       .RunWorkerAsync()
                   End With
                   Me.stateB = BackgroundWorkerState.Running
                   Me.mreSync.WaitOne()

               Case Else
                   Throw New InvalidOperationException("In order to run the BackgroundWorker instance it must be stopped or completed.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Asynchronouslly run the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to run the BackgroundWorker instance it must be stopped or completed.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub RunAsync()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Stopped, BackgroundWorkerState.Completed
                   With Me.Worker
                       .WorkerSupportsCancellation = True
                       .WorkerReportsProgress = True
                       .RunWorkerAsync()
                   End With
                   Me.stateB = BackgroundWorkerState.Running

               Case Else
                   Throw New InvalidOperationException("In order to run the BackgroundWorker instance it must be stopped or completed.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Asynchronouslly pause the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to pause the BackgroundWorker instance it must be running.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub PauseAsync()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Running
                   Me.isPauseRequested = True
                   Me.stateB = BackgroundWorkerState.Paused
                   Me.mreAsync.Reset()

               Case Else
                   Throw New InvalidOperationException("In order to pause the BackgroundWorker instance it must be running.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Resume the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to resume the BackgroundWorker instance it must be paused.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub [Resume]()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Paused
                   Me.stateB = BackgroundWorkerState.Running
                   Me.isPauseRequested = False
                   Me.mreAsync.Set()

               Case Else
                   Throw New InvalidOperationException("In order to resume the BackgroundWorker instance must be paused.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Cancel the background work.
   ''' <para></para>
   ''' It blocks the caller thread until the remaining work is done.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to cancel the BackgroundWorker instance it must be running or paused.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub Cancel()

       Me.isCancelSyncRequested = True
       Me.CancelAsync()
       Me.mreSync.WaitOne()
       Me.isCancelSyncRequested = False

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Asynchronouslly cancel the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to cancel the BackgroundWorker instance it must be running or paused.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub CancelAsync()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.CancellationPending
                   Exit Sub

               Case BackgroundWorkerState.Running, BackgroundWorkerState.Paused
                   Me.mreAsync.Set() ' Resume thread if it is paused.
                   Me.stateB = BackgroundWorkerState.CancellationPending
                   Me.Worker.CancelAsync() ' Cancel it.

               Case Else
                   Throw New InvalidOperationException("In order to cancel the BackgroundWorker instance must be running or paused.")

           End Select

       End If

   End Sub

#End Region

#Region " Private Methods "

   <DebuggerStepperBoundary>
   Private Sub DoSomething()
       Thread.Sleep(TimeSpan.FromSeconds(5))
   End Sub

#End Region

#Region " Event-Handlers "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Handles the <see cref="BackgroundWorker.DoWork"/> event of the <see cref="Worker"/> instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="DoWorkEventArgs"/> instance containing the event data.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepperBoundary>
   Private Sub Worker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
   Handles Worker.DoWork

       Dim progress As Integer

       Dim lock As Object = ""
       SyncLock lock

           For i As Integer = 0 To 100

               If (Me.Worker.CancellationPending) Then
                   e.Cancel = True
                   Exit For

               Else
                   If (Me.isPauseRequested) Then ' Pause this thread right here.
                       Me.mreAsync.WaitOne(Timeout.Infinite)
                   End If

                   Me.DoSomething()

                   If Me.Worker.WorkerReportsProgress Then
                       progress = i
                       Me.Worker.ReportProgress(progress)
                   End If

               End If

           Next i

       End SyncLock

       If (Me.Worker.WorkerReportsProgress) AndAlso Not (Me.Worker.CancellationPending) AndAlso (progress < 100) Then
           Me.Worker.ReportProgress(percentProgress:=100)
       End If

       If (Me.isRunSync) OrElse (Me.isCancelSyncRequested) Then
           Me.mreSync.Set()
       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Handles the <see cref="BackgroundWorker.ProgressChanged"/> event of the <see cref="Worker"/> instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="ProgressChangedEventArgs"/> instance containing the event data.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepperBoundary>
   Private Sub Worker_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
   Handles Worker.ProgressChanged

       Console.WriteLine(String.Format("Work Progress: {0:00.00}%", e.ProgressPercentage))

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Handles the <see cref="BackgroundWorker.RunWorkerCompleted"/> event of the <see cref="Worker"/> instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="RunWorkerCompletedEventArgs"/> instance containing the event data.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepperBoundary>
   Private Sub Worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
   Handles Worker.RunWorkerCompleted

       If (e.Cancelled) Then
           Console.WriteLine("Background work cancelled.")

       ElseIf (e.Error IsNot Nothing) Then
           Console.WriteLine("Background work error.")

       Else
           Console.WriteLine("Background work done.")

       End If

       Me.stateB = BackgroundWorkerState.Completed

   End Sub

#End Region

#Region " IDisposable Implementation "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Flag to detect redundant calls when disposing.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isDisposed As Boolean
   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Releases all the resources used by this instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub Dispose() Implements IDisposable.Dispose

       Me.Dispose(isDisposing:=True)
       GC.SuppressFinalize(obj:=Me)

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
   ''' <para></para>
   ''' Releases unmanaged and, optionally, managed resources.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="isDisposing">
   ''' <see langword="True"/> to release both managed and unmanaged resources;
   ''' <see langword="False"/> to release only unmanaged resources.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Private Sub Dispose(ByVal isDisposing As Boolean)

       If (Not Me.isDisposed) AndAlso (isDisposing) Then

           If (Me.Worker IsNot Nothing) Then
               Me.Worker.Dispose()
               Me.Worker = Nothing

               With Me.mreSync
                   .SafeWaitHandle.Close()
                   .Dispose()
               End With

               With Me.mreAsync
                   .SafeWaitHandle.Close()
                   .Dispose()
               End With

               Me.isRunSync = False
               Me.stateB = BackgroundWorkerState.Stopped
           End If

       End If

       Me.isDisposed = True

   End Sub

#End Region

End Class

#End Region


Ejemplo de uso:
Código (vbnet) [Seleccionar]
Public Class Form1

   Friend Worker As MyBackgroundWork

   Private Sub Run_Click() Handles Button_Start.Click

       If (Me.Worker IsNot Nothing) Then
           Select Case Me.Worker.State
               Case BackgroundWorkerState.Running, BackgroundWorkerState.Paused
                   Me.Worker.Cancel()
               Case Else
                    Do Nothing.
           End Select
       End If

       Me.Worker = New MyBackgroundWork
       Me.Worker.RunAsync()

   End Sub

   Private Sub Pause_Click() Handles Button_Pause.Click
       Me.Worker.PauseAsync()
   End Sub

   Private Sub Resume_Click() Handles Button_Resume.Click
       Me.Worker.Resume()
   End Sub

   Private Sub Cancel_Click() Handles Button_Cancel.Click
       Me.Worker.CancelAsync()
   End Sub

End Class


Saludos








TrashAmbishion

Pues si que funcionaba el problema radicaba en que yo estaba haciendo un While hasta esperar que se disparara el evento de que ya se habia terminado el BW pero nose donde fue que leí que usar Application.DoEvents no era recomendable que era preferible usar un Thread.Slepp...

En cuanto cambie el Thread.Slepp para DoEvents funciono todo de maravillas..

El While estaba mirando una variable Booleana que se ponia a TRUE en el evento Complete del BW.

Sabrias porque sucedia eso ?

Salu2 y gracias por el código..

Ya terminé el programa y te incluí en los créditos asi como tu página despues te mando captura.

snetcancerbero

estimado Eleкtro, yo estoy en la misma situacion que ud. necesito encarecidamente de ser posible el programa completo, poseo cierto conocimiento de programacion y decidi crar una herramienta para controlar los jugadores de bf3 para que no sen crack en el juego y me dispuse a desemporbar mis conocimiento en c#, no me es facil pero tengo que hacerlo por el bien comun, y mi busqueda me envio aqui justo con mis propias inquietudes, porfavor necesito que me responda, gracias.

Eleкtro

Cita de: TrashAmbishion en 20 Septiembre 2016, 03:44 AM
El While estaba mirando una variable Booleana que se ponia a TRUE en el evento Complete del BW.

Sabrias porque sucedia eso ?

Pues no se muy bien a que te refieres, en el búcle que compartiste en el código de arriba no estás evaluando en ningún momento la variable StopState, pero bueno, ¡ya lo resolviste!.




Cita de: snetcancerbero en 22 Septiembre 2016, 20:24 PMestimado Eleкtro, yo estoy en la misma situacion que ud. necesito encarecidamente de ser posible el programa completo

Hola

Creo que te confundiste de persona y que tu mensaje en realidad va dirigido a @TrashAmbishion, puesto que el programa no es mio, jeje.

Saludos!








TrashAmbishion

Cita de: snetcancerbero en 22 Septiembre 2016, 20:24 PM
estimado Eleкtro, yo estoy en la misma situacion que ud. necesito encarecidamente de ser posible el programa completo, poseo cierto conocimiento de programacion y decidi crar una herramienta para controlar los jugadores de bf3 para que no sen crack en el juego y me dispuse a desemporbar mis conocimiento en c#, no me es facil pero tengo que hacerlo por el bien comun, y mi busqueda me envio aqui justo con mis propias inquietudes, porfavor necesito que me responda, gracias.

Pues si es conmigo la cosa el soft ya esta realizado en fase de pruebas...

Saludos y gracias nuevamente elektro