2010-02-15 12 views
34

tengo obj objeto que es tercera componente partido,tiempo de espera establecido para una operación

// this could take more than 30 seconds 
int result = obj.PerformInitTransaction(); 

No sé lo que está pasando en el interior. Lo que sé es que si demora más tiempo, falla.

cómo configurar un mecanismo de tiempo de espera para esta operación, de modo que si lleva más de 30 segundos simplemente lanzo MoreThan30SecondsException?

Respuesta

66

Se puede ejecutar la operación en un hilo separado y luego poner un tiempo de espera en el hilo se unen a la operación:

using System.Threading; 

class Program { 
    static void DoSomething() { 
     try { 
      // your call here... 
      obj.PerformInitTransaction();   
     } catch (ThreadAbortException) { 
      // cleanup code, if needed... 
     } 
    } 

    public static void Main(params string[] args) { 

     Thread t = new Thread(DoSomething); 
     t.Start(); 
     if (!t.Join(TimeSpan.FromSeconds(30))) { 
      t.Abort(); 
      throw new Exception("More than 30 secs."); 
     } 
    } 
} 
+1

@Bomboca: me removió su edición, el 'Exception' estoy lanzando no debe ser un' ThreadAbortException', que es algo tirado por el CLR cuando una llamada para 'Abortar' está hecho. –

+0

perdón por eso y gracias por la entrada :) –

+2

Es una llamada de bloqueo, si necesita el hilo principal, ¡haga otras cosas en este momento, esto no funcionará! – feldeOne

1

lo podría hacer en invocar el método en un hilo y sobre el tiempo de espera, abortar el hilo y elevar la excepción Además, deberá manejar la excepción ThreadBorted en este caso.

+0

Tiene razón sobre ThreadAbortedException, +1. –

0

Hay un buen ejemplo de una solución genérica para esto utilizando una clase auxiliar here.

Utiliza el delegado de Acción para evitar la creación/destrucción de subprocesos que se muestra en el ejemplo anterior.

Espero que esto ayude.

2

Debe tener cuidado al abortar una operación como esta, especialmente porque en un componente de un tercero usted (posiblemente) no tiene acceso al código para modificar.

Si cancela la operación, no sabrá en qué estado ha dejado la clase subyacente. Por ejemplo, puede haber adquirido un bloqueo, y su información ha provocado que ese bloqueo no se libere. Incluso si destruye el objeto después de abortar la operación, puede haber alterado algún estado que sea global para él y, por lo tanto, no podrá crear de manera fiable una nueva instancia sin reiniciar.

6

Si no desea bloquear el hilo principal puede utilizar un System.Threading.Timer:

private Thread _thread; 

void Main(string[] args) 
{ 
    _thread = new ThreadStart(ThreadEntry); 
    _thread.Start(); 
    Timer timer = new Timer(Timeout,null,30000,Timeout.Infinite); 
} 


void ThreadEntry() 
{ 
    int result = obj.PerformInitTransaction(); 
} 

void TimeOut(object state) 
{ 
    // Abort the thread - see the comments 
    _thread.Abort(); 

    throw new ItTimedOutException(); 
} 

Jon Skeet tiene una forma menos contundente (Shutting Down Worker Threads Gracefully) de detener el hilo de abortar.

Sin embargo, como usted no tiene el control de las operaciones que hace PerformInitTransaction(), no hay mucho que pueda hacer cuando Abort falla y deja el objeto en un estado no válido. Como se mencionó, si puede limpiar cualquier cosa que haya dejado PerformInitTransaction, puede hacerlo capturando el ThreadAbortException, aunque como es una llamada de un tercero, significará adivinar el estado en el que dejó el método.

El PerformInitTransaction realmente debería ser el que proporcione el tiempo de espera.

10

Más simple uso de Task.Wait(TimeSpan):

using System.Threading.Tasks; 

var task = Task.Run(() => obj.PerformInitTransaction()); 
if (task.Wait(TimeSpan.FromSeconds(30))) 
    return task.Result; 
else 
    throw new Exception("Timed out"); 
+0

Esto es muy simple y está disponible desde .net 4.0. –

+0

Esto no matará el hilo aunque –

Cuestiones relacionadas