Qual é a melhor maneira de executar métodos sequenciais?
Pergunta
Trabalhar em um projeto onde um conjunto sequencial de métodos deve ser executado a cada x
segundos.No momento, tenho os métodos contidos em outro "método pai" e apenas os chamo sequencialmente, logo após o outro.
class DoTheseThings()
{
DoThis();
NowDoThat();
NowDoThis();
MoreWork();
AndImSpent();
}
Cada método deve ser executado com êxito sem lançar uma exceção antes que a próxima etapa possa ser executada.Então agora envolvi cada um desses métodos com um while
e try..catch
, então no catch
execute esse método novamente.
while( !hadError )
{
try
{
DoThis();
}
catch(Exception doThisException )
{
hadError = true;
}
}
Parece fedorento e não muito seco.Existe uma maneira melhor de fazer isso, então não estou agrupando nenhuma nova funcionalidade nos mesmos métodos.Algum tipo de coleção de delegados não é a maneira correta de implementar isso?
Existe uma solução mais "adequada"?
Solução
Action[] work=new Action[]{new Action(DoThis), new Action(NowDoThat),
new Action(NowDoThis), new Action(MoreWork), new Action(AndImSpent)};
int current =0;
while(current!=work.Length)
{
try
{
work[current]();
current++;
}
catch(Exception ex)
{
// log the error or whatever
// maybe sleep a while to not kill the processors if a successful execution depends on time elapsed
}
}
Outras dicas
Não é algum tipo de coleção de delegados a maneira correta de implementar isso?
O delegado é uma maneira possível de resolver esse problema.
Basta criar um delegado algo como:
delegado público void workdelegate ();
e coloque -os na lista de Arrays, que você pode iterar.
Eu tenho uma crença religiosa pessoal de que você não deve capturar o sistema.Exception, ou mais precisamente, você deve pegar apenas as exceções que sabe como lidar.
Dito isto, vou assumir que cada um dos métodos que você está chamando estão fazendo algo diferente e pode resultar em diferentes exceções sendo jogadas. O que significa que você provavelmente precisaria ter manipuladores diferentes para cada método.
Se você segue minha religião também e a segunda afirmação é verdadeira, não está repetindo o código desnecessariamente. A menos que você tenha outros requisitos, minhas recomendações para melhorar seu código seriam:
1) Coloque a captura de tentativa em cada método, não em torno de cada chamada de método.
2) Peça às capturas dentro de cada método capturar apenas as exceções que você conhece.
http://blogs.msdn.com/fxcop/archive/2006/06/14/631923.aspx http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx http://www.joelonsoftware.com/articles/wrong.html
HTH ...
seu exemplo parece ok ..é seco, mas fará bem o trabalho!!na verdade, se esses métodos executarem acesso ao banco de dados.você pode usar a transação para garantir a integridade ...
se você estiver lidando com variáveis compartilhadas para programas multi threader.é mais limpo usar a sincronização.a coisa mais importante na codificação é que você escreva o código adequado...que tem menos bugs..e fará a tarefa corretamente.
public void DoTheseThings()
{
SafelyDoEach( new Action[]{
DoThis,
NowDoThat,
NowDoThis,
MoreWork,
AndImSpent
})
}
public void SafelyDoEach( params Action[] actions )
{
try
{
foreach( var a in actions )
a();
}
catch( Exception doThisException )
{
// blindly swallowing every exception like this is a terrible idea
// you should really only be swallowing a specific MyAbortedException type
return;
}
}
Qual seria a razão pela qual um erro estava ocorrendo?
Se esse fosse um problema de recurso, como acesso a algo como uma conexão ou objeto, convém ver o uso de monitores, semáforos ou apenas bloqueio.
lock (resource)
{
Dosomething(resource);
}
Dessa forma, se um método anterior estiver acessando o recurso, você poderá esperar até que ele libere o recurso para continuar.
Idealmente, você não deve executar um loop para executar algo cada vez que falhar. Está falhando, você gostaria de saber sobre o problema e corrigi -lo. Ter um loop para sempre continuar tentando não é o caminho certo para ir aqui.
Eu faria o que ovidiu -pacurar sugere, só eu usaria um foreach
Faça um loop e saia lidando com índices de matriz até o compilador.
Abordagem simples de delegado:
Action<Action> tryForever = (action) => {
bool success;
do {
try {
action();
success = true;
} catch (Exception) {
// should probably log or something here...
}
} while (!success);
};
void DoEverything() {
tryForever(DoThis);
tryForever(NowDoThat);
tryForever(NowDoThis);
tryForever(MoreWork);
tryForever(AndImSpent);
}
Abordagem de pilha:
void DoEverything() {
Stack<Action> thingsToDo = new Stack<Action>(
new Action[] {
DoThis, NowDoThat, NowDoThis, MoreWork, AndImSpent
}
);
Action action;
while ((action = thingsToDo.Pop()) != null) {
bool success;
do {
try {
action();
success = true;
} catch (Exception) {
}
} while (!success);
}