如何最好地执行顺序方法?

4

我正在处理一个项目,需要每隔x秒运行一组连续的方法。目前,我将这些方法包含在另一个“父方法”中,并依次调用它们。

class DoTheseThings()
{
    DoThis();
    NowDoThat();
    NowDoThis();
    MoreWork();
    AndImSpent();
}

每个方法在执行下一步之前必须成功运行而不抛出异常。因此,我现在用whiletry..catch包装了每个方法,然后在catch中再次执行该方法。
while( !hadError )
{
    try
    {
         DoThis();
    }
    catch(Exception doThisException )
    {
         hadError = true;
    }

}

这个看起来有点臭,也不太干燥。有没有更好的方法可以做到在同一方法中不包含任何新功能。委托集合是实现这一点的正确方式吗?

是否有更“适当”的解决方案?

8个回答

5
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  
   }
}

有什么理由不使用内置的 Action 委托? - Mark Brackett
如果你觉得需要注释“SimpleDelegate”,那么它的名字本身就应该是这样。 - Aidan Ryan
如果操作失败,它需要重新运行该操作。 - nyxtom
它会重新运行,因为如果workcurrent中发生异常,current++不会执行。 - Ovidiu Pacurar

2

使用某种委托集合来实现这个功能是正确的方法吗?

委托是解决这个问题的一种可能方式。

只需创建一个类似于以下内容的委托:

public delegate void WorkDelegate();

然后将它们放入可迭代的arraylist中即可。


2
我有一个个人的宗教信仰,认为你不应该捕获System.Exception,或者更准确地说,你只应该捕获你知道如何处理的异常。
话虽如此,我会假设你调用的每个方法都在做不同的事情,并且可能导致抛出不同的异常。这意味着你可能需要为每个方法编写不同的处理程序。
如果你也遵循我的信仰,并且第二个陈述是正确的,那么你不会不必要地重复代码。除非你有其他要求,我对改进你的代码的建议是:
1)在每个方法中放置try-catch,而不是在每个方法调用周围。
2)在每个方法的catch中仅捕获你知道的异常。

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 ...


1
或者,仍然使用委托方法,但同时传递一个 Predicate<Exception> 来判断是否应该捕获或抛出异常。 - Mark Brackett

1
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;
    }
}

不要重复失败的操作。 - Mark Brackett

1

你的例子看起来还不错..虽然有点枯燥,但是可以很好地完成工作!实际上,如果这些方法执行数据库访问..你可以使用事务来确保完整性...

如果你正在处理多线程程序的共享变量..最好使用同步来保持代码的清洁..编码中最重要的事情是编写正确的代码..这样会减少错误..并且能够正确地完成任务..


0

出现错误的原因是什么?

如果这是资源问题,例如访问连接或对象之类的东西,那么您可能需要考虑使用监视器、信号量或仅锁定。

lock (resource) 
{
    Dosomething(resource);
}

这种方法可以使得如果之前的某个方法正在访问资源,那么你可以等待它释放资源后再继续执行。

理想情况下,你不应该通过循环来执行每次失败的操作。如果出现了问题,则需要知道并解决它。一直尝试而不断进行循环并不是正确的做法。


0

简单的委托方法:

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);
}

堆栈方法:

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);
  }

0
我会采用Ovidiu Pacurar所建议的方法,只不过我会使用foreach循环,并且将处理数组索引的任务交给编译器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接