En determinados procesos como por ejemplo un proceso de monitorización, puede ser crítico que nunca se produzca este enganche. Aquí va mi propuesta de lo que podría ser una librería para controlar el Timeout. Se trata de hacer la llamada en una segunda hebra y esperar un tiempo máximo para la consecución de la misma.
Se plantean dos problemas; el paso de parámetros y la captura de excepciones; La solución expone entre otras una clase estática que a su vez contiene cuatro métodos estáticos genéricos:
public static void RunV(int milisegundos, ThreadStart metodo)
public static T RunG<T, U>(int milisegundos, U par, Func<T, U> metodo)
public static T RunG<T, U, V>(int milisegundos, U paru, V parv, Func<T, U, V> metodo)
public static T RunG<T, U, V, W>(int milisegundos, U paru, V parv, W parw,Func<T, U, V, W> metodo)
tambien se definen tres delegados genéricos:
public delegate T Func<T,U>(U parametro);
public delegate T Func<T, U, V>(U parametrou, V parametrov);
public delegate T Func<T, U, V, W>(U parametrou, V parametrov, W parametrow);
además del archiconocido delegado void ThreadStart().
Con lo cual contempla llamadas a métodos void funcion() y métodos con retorno cualquier tipo con hasta tres argumentos de cualquier tipo.
Estoy de acuerdo que hacer un Abort de un Thread no es una opción muy recomendable, pero no es tan mala si la única alternativa que queda es ir al Task Manager y matar el proceso.
A continuación se muestra el código que implementa la librería:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Timeouts
{
public delegate T Func<T,U>(U parametro);
public delegate T Func<T, U, V>(U parametrou, V parametrov);
public delegate T Func<T, U, V, W>(U parametrou, V parametrov, W parametrow);
internal class Envoltura
{
private Exception ex = null;
private ThreadStart metodo;
public void Run(ThreadStart metodo, int milisegundos)
{
this.metodo = metodo;
Thread t = new Thread(run);
t.Start();
bool final = t.Join(milisegundos);
if (!final)
{
t.Abort();
TimeoutSException to = new TimeoutSException();
to.Timeout = milisegundos;
throw to;
}
else
{
if (this.ex != null)
throw this.ex;
return;
}
}
private void run()
{
try
{
metodo();
}
catch (Exception e)
{
ex = e;
}
}
}
internal class Envoltura<T,U>
{
private Exception ex=null;
private U parametro;
private Func<T, U> metodo;
private T retorno;
public Envoltura(U parametro)
{
this.parametro = parametro;
}
public T Run(Func<T, U> metodo, int milisegundos)
{
this.metodo = metodo;
Thread t = new Thread(run);
t.Start();
bool final = t.Join(milisegundos);
if (!final)
{
t.Abort();
TimeoutSException to = new TimeoutSException();
to.Timeout = milisegundos;
throw to;
}
else
{
if (this.ex != null)
throw this.ex;
return this.retorno;
}
}
private void run()
{
try
{
this.retorno = metodo(parametro);
}
catch (Exception e)
{
ex = e;
}
}
}
internal class Envoltura<T, U, V>
{
private Exception ex = null;
private U parametrou;
private V parametrov;
private Func<T, U, V> metodo;
private T retorno;
public Envoltura(U parametrou, V parametrov)
{
this.parametrou = parametrou;
this.parametrov = parametrov;
}
public T Run(Func<T, U, V> metodo, int milisegundos)
{
this.metodo = metodo;
Thread t = new Thread(run);
t.Start();
bool final = t.Join(milisegundos);
if (!final)
{
t.Abort();
TimeoutSException to = new TimeoutSException();
to.Timeout = milisegundos;
throw to;
}
else
{
if (this.ex != null)
throw this.ex;
return this.retorno;
}
}
private void run()
{
try
{
this.retorno = metodo(parametrou, parametrov);
}
catch (Exception e)
{
ex = e;
}
}
}
internal class Envoltura<T, U, V, W>
{
private Exception ex = null;
private U parametrou;
private V parametrov;
private W parametrow;
private Func<T, U, V, W> metodo;
private T retorno;
public Envoltura(U parametrou, V parametrov, W parametrow)
{
this.parametrou = parametrou;
this.parametrov = parametrov;
this.parametrow = parametrow;
}
public T Run(Func<T, U, V, W> metodo, int milisegundos)
{
this.metodo = metodo;
Thread t = new Thread(run);
t.Start();
bool final = t.Join(milisegundos);
if (!final)
{
t.Abort();
TimeoutSException to = new TimeoutSException();
to.Timeout = milisegundos;
throw to;
}
else
{
if (this.ex != null)
throw this.ex;
return this.retorno;
}
}
private void run()
{
try
{
this.retorno = metodo(parametrou, parametrov, parametrow);
}
catch (Exception e)
{
ex = e;
}
}
}
public class TimeoutSException : Exception
{
private int timeout;
public int Timeout
{
get { return timeout; }
set { timeout = value; }
}
}
public class Timeout
{
public static void RunV(int milisegundos, ThreadStart metodo)
{
Envoltura env = new Envoltura();
env.Run(metodo, milisegundos);
}
public static T RunG<T, U>(int milisegundos, U par, Func<T, U> metodo)
{
Envoltura<T, U> env = new Envoltura<T, U>(par);
return env.Run(metodo, milisegundos);
}
public static T RunG<T, U, V>(int milisegundos, U paru, V parv,
Func<T, U, V> metodo)
{
Envoltura<T, U, V> env = new Envoltura<T, U, V>(paru, parv);
return env.Run(metodo, milisegundos);
}
public static T RunG<T, U, V, W>(int milisegundos, U paru, V parv,
W parw,Func<T, U, V, W> metodo)
{
Envoltura<T, U, V, W> env = new Envoltura<T, U, V, W>(paru, parv, parw);
return env.Run(metodo, milisegundos);
}
}
}
Y un programilla que la prueba:
using System;
using System.Collections.Generic;
using System.Text;
using Timeouts;
namespace Probe
{
public class Pruebas
{
public string Variable="";
public void metodov()
{
System.Threading.Thread.Sleep(500);
Variable += "hola,";
}
public string metodo(string par, string par2)
{
return par + par2;
}
public string metodo2(string par, string par2, int par3)
{
int i = 6 / par3;
return par + par2 + "-" + par3.ToString();
}
}
class Program
{
static void Main(string[] args)
{
//con void
Pruebas p = new Pruebas();
Timeout.RunV(1000, p.metodov);
Timeout.RunV(1000, p.metodov);
try
{
Timeout.RunV(100, p.metodov);
}
catch (TimeoutSException e) { Console.WriteLine("Timeout: " + e.Timeout.ToString() + " ms"); }
Console.WriteLine(p.Variable);
//inline con un parametro
string pp = Timeout.RunG<string, string>(10000, "pepe", delegate(string par)
{
string ret = par.ToUpper();
return ret;
});
Console.WriteLine(pp);
//otra prueba con dos parametros
string ret2 = Timeout.RunG<string, string, string>(1000, "Pp", "potamo", p.metodo);
Console.WriteLine(ret2);
//con tres
string st = Timeout.RunG<string,string,string,int>(1000, "Pp", "potamo",7, p.metodo2);
Console.WriteLine(st);
//las excepciones generadas en el delegado son capturadas.
try
{
Console.WriteLine(Timeout.RunG<string, string, string, int>(
1000, "Pp", "potamo", 0, p.metodo2));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
}
}
jordan 6 black infrared
ResponderEliminarnorth face coats
hermes belt
fitflop outlet store usa
under armour outlet
burberry scarf
gucci shoes
coach handbags
burberry sale
kevin durant shoes
north face jackets
converse shoes sale
coach factory outlet
air jordan 14
coach factory outlet online
louboutin outlet
fitflop sale
nike nfl jerseys 2015
north face outlet store
ugg boots
reebok outlet
michael kors handbags
christian louboutin sale
north face jackets clearance
new kevin durant shoes
nike clearance
toms outlet
dior handbags
michael kors outlet store
fitflops clearance
kate spade sale
jordan 12
ugg boots
coach purses sale
gucci outlet
wholesale jordans
canada goose clearance
1030wjl
1 columbia outlet
ResponderEliminarnike air max
polo shirts
polo shirts for women
north face outlet 70% off
cheap michael kors handbags
air jordan retro 6
salvatore ferragamo outlet
north face clearance
mbt shoes clearance outlet
reebok shoes outlet
polo ralph lauren factory store
celine handbags
christian louboutin shoes
michael kors handbags
fitflops online
jordan 6
ralph lauren extra 25% off
michael kors outlet
air jordan 11
coach factory online sale
jordan shoes
kd shoes
coach handbags outlet
coach shoes for women
gucci outlet
abercrombie and fitch outlet
ferragamo shoes outlet
air jordan 11 legend blue
michael kors factory outlet online
michael kors store
all jordan shoes
ugg boots sale
fitflop sandals for women
gucci outlet
cheap canada goose coats
nike running shoes
1030wjl