Pregunta

VB.NET 2010, .NET 4

Hola a todos,

Tengo un objeto System.Timers.Timer que hace algún trabajo en su caso transcurrido:

Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
    MasterTimer.Enabled = False
    '...work...
    MasterTimer.Enabled = True
End Sub

Mi problema es que el trabajo que se está haciendo a veces se atasca. Parte del trabajo es la comunicación en serie por lo que podría estar recibiendo atascado espera de una respuesta de algo. Ya he modificado mi código de comunicación en serie un poco de esperar para resolver el problema. Sin embargo, este temporizador es básicamente el latido del corazón de una aplicación de control de la producción y es muy mala si se tratara de detener por cualquier motivo. Estaba pensando que podría ser bueno para poner en un tiempo de espera a prueba de fallos de manera que, si el "trabajo" está tomando demasiado tiempo, el temporizador podría volver a habilitar a sí mismo y vuelve a intentarlo. Estaba pensando en algo como esto:

Mover el trabajo en una subrutina y crear un delegado:

Private Delegate Sub WorkDelegate()
Private Sub Work()
   '...work...
End Sub

Llamada la obra mediante la invocación del delegado y luego usar WaitOne (tiempo de espera) en la IAsyncResult para especificar un tiempo de espera:

Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
    MasterTimer.Enabled = False
    Dim workDel as New WorkDelegate(AddressOf Work)
    Dim result as IAsyncResult = workDel.BeginInvoke
    result.AsyncWaitHandle.WaitOne(CInt(MasterTimer.Interval))
    MasterTimer.Enabled = True
End Sub

Sin embargo, mi pregunta es: ¿Podría esta causa un problema si trabajo () realmente estaba en algún lugar atascado? En ese sería volver a entrar en una subrutina que ya se está ejecutando? ¿Hay una manera de abortar trabajo () si no ha terminado después de que el tiempo de espera? En otras palabras, sólo cesará ejecución del trabajo () si es falso result.IsCompleted después WaitOne?

No entiendo muy bien esto muy bien así, los comentarios serán bienvenidos. Tal vez hay una forma totalmente diferente de abordar esto que yo no sepa?

Muchas gracias de antemano!

Me gustaría añadir algo:

A pesar de que tengo la intención de hacer algunas reescrituras como por sugerencias de Hans, que ya había programado una jornada de pruebas para tratar de aislar el origen de este error. Hasta el momento, sólo se ha producido cuando se ejecuta la aplicación compilada. He pasado hoy (y algunos ayer) tratando de reproducir la congelación mientras se ejecuta en modo de depuración de modo que tal vez podría añadir algunos puntos de interrupción y averiguar lo que está pasando. Hasta el momento, el programa no se ha congelado en modo de depuración. Me pregunto si hay algo diferente en el entorno de depuración que podría explicar esto. Tal vez sólo sea que estoy siendo "suerte", pero me he encontrado probablemente tres veces la longitud promedio de tiempo después del cual el programa se congeló cuando se ejecuta el ejecutable ... Una vez más, estoy bastante ignorante, pero ¿hay algo único en el entorno de depuración que podría explicar esto? Voy a actualizar de nuevo si se congela.

¿Fue útil?

Solución

Esto va mal en la primera línea del código. La clase System.Timers.Timer es bastante repulsivo, no hay absolutamente ninguna garantía de que la llamada Stop () evitará que otra llamada. El temporizador utiliza ThreadPool.QueueUserWorkItem para realizar la llamada controlador de eventos transcurrido. Si el conjunto de subprocesos está ocupado Esto puede llegar a hacer cola varias llamadas, a la espera de obtener el visto bueno del programador de TP para empezar a correr. Parando el cronómetro no impide que los hilos esperando que se ejecute. Sin necesidad de utilizar una cerradura, esos hilos va a intensificar el uno del otro mal y estropear su estado de comunicación.

una caja fuerte es System.Threading.Timer con un período de cero de manera que obtendrá sólo una devolución de llamada. Recargar el temporizador con su método de cambio ().

Llamando al método de un delegado BeginInvoke () y luego el bloqueo en él completando no tiene sentido. Sólo tiene que llamar Invoke (). que salva de la quema de otro hilo.

Sí, si el método de 'Trabajo' nunca regresa entonces usted tiene un problema. Un uno insoluble.

Una gran cantidad de esta miseria podría desaparecer si se evita el uso de votación para ver si hay algo disponible en el puerto serie. Deja que te diga que hay algo que vale la pena pasando. Se genera el evento DataReceived, en un hilo de subprocesos, cada vez que hay al menos un byte en el búfer. El uso de su propiedad WriteTimeout es también una excelente manera de evitar quedarse atascado cuando algo anda mal con el protocolo de comunicación o el dispositivo. Dedicando un hilo y haciendo llamadas de bloqueo de lectura funciona bien también.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top