1

在这里受到更聪明的头脑的温和批评,我将我对 MessageBox.Show() 的调用切换到将行写入 StringBuilder ,然后将其保存到文件中,两者都来自应用程序的自定义异常处理程序:

public static void ExceptionHandler(Exception ex, string location)
{
    try
    {
        if (inDebugMode)
        {
            LogMsgs.Append(string.Format("{0}\r\n", ex.Message)); 
            DateTime dt = DateTime.Now;
            string timeAsStr = string.Format("{0}_{1}_{2}_{3}.txt", dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
            using (StreamWriter file = new StreamWriter(timeAsStr))
            {
                // If the app crashes, this is how the file is written; if it doesn't, it's written
                // in frmCentral.Form1_Closing()
                file.WriteLine(LogMsgs.ToString());
            }
        }
        MessageBox.Show("Exception: " + ex.Message + "\n\nLocation: " + location, GetFormTitle("CCR: " + ex.GetType().FullName,"",""));
    }

(......它被称为这样的:

catch (Exception ex )
{
    CCR.ExceptionHandler(ex, "WriteXML.WriteFile");
    . . .

) ...以及来自主窗体的 Closed() 事件:

private void frmCentral_Closed(object sender, EventArgs e)
{
    if (CCR.inDebugMode)
    {
        DateTime dt = DateTime.Now;
        string timeAsStr = string.Format("{0}_{1}_{2}_{3}.txt", dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
        using (StreamWriter file = new StreamWriter(timeAsStr))
        {
            // If the app closes normally, this is how the file is written; if it doesn't, 
            // (it crashed) it's written in PDAClient.ExceptionHandler()
            file.WriteLine(CCR.LogMsgs.ToString());
        }
    }
} // frmCentral_Closed

直到今天早些时候,这才有效。我没有更改该代码。但是现在,无论代码是否崩溃(我可以从主窗体关闭它),文件都没有被写入(至少没有写入之前写入的位置,即手持设备的根目录)。

我正在添加类似的消息:

CCR.LogMsgs.Append(string.Format("DBCommand exception: {0}\r\n", ex.Message));

..并且 inDebugMode 布尔值确实被设置为 true 而无处为 false:

public static bool inDebugMode = true; //TODO: Change this to false before deploying.

是什么导致了这种恶意的遗漏?

更新

要回答 jp2code:

这就是 ExceptionHandler 在其 catch 块中所做的:

catch(Exception exc)
{
    MessageBox.Show("Exception Handler generated an exception!\n" + exc.Message + "\n\nCalling Location: " + location, GetFormTitle("CCR: " + exc.GetType().FullName,"",""));
}

请注意,我没有编写此代码,因此我经常(通常?)不知道其中大部分背后的动机或心态。对我来说,这似乎比 Italienfest 更意大利面,但也许我只是不理解它。

很多东西并不是它们在代码中出现的那样,例如,被命名为布尔函数的 void 函数,以及你会认为(无论如何我会)的 ExceptionHandler() 方法,它是一个全局/catch-所有异常处理程序,但实际上必须在整个代码中从 catch 块显式调用才能执行。

另外:我尝试实现 errHndlrLock 代码,但得到编译错误消息,“非静态字段、方法或属性 'PDAClient.SSCS.errHndlrLock' 需要对象引用

更新 2

今天又开始工作了;一定是内存问题或类似问题 - 尽管我昨天确实进行了热启动,没有喘息的机会。所以:它起作用了,它突然不起作用,就像突然(一夜之间)一样,它又开始起作用了。

更新 3

我认为这是在令人难以置信的神秘消失的调试日志文本文件的情况下发生的事情的线索。当我今天打开最近的那些时,它们充满了:

StackOverflowException
StackOverflowException
StackOverflowException
StackOverflowException
StackOverflowException
StackOverflowException
StackOverflowException

......这些已经够多了,我想整个shebang都决定去度假了。不过,现在它又暂停了——这首 CE 爵士乐比我祖母的馅饼皮还要脆。

4

2 回答 2

2

我可能是错的,但看起来您的流缓冲区没有被刷新。

尝试添加

file.Flush();

在您致电 writeline 之后。另外,我没有看到您明确关闭流的地方。这样做是个好习惯。

于 2013-03-27T21:53:27.937 回答
2

Nat 可能会对这个Flush电话感兴趣。我给了他+1。

可能发生的另一件事(我遇到的)是多个项目试图一次访问您的异常处理程序。

假设您正在关闭表单,并且在您的一种方法中捕获了异常。现在,您有两 (2) 个例程试图timeAsStr一次访问您的文件,这是不可能的。

一个解决方案是lock在您的异常处理程序例程中添加一个:

private object errHndlrLock = new Object();

public void ExceptionHandler(Exception ex, string location) {
  lock (errHndlrLock) {
    // continue with your code
  }
}

想到的另一件事:我看到您的异常处理程序代码显示了try/catch块的一部分。

问:你如何处理你捕获的异常?

如果您递归调用相同的方法,这可能是您丢失信息的原因。

如果您想采用不同的方法,您可以使用Queue, 定义的全局类,以及您的StreamWriter:

class CCR {

  private Queue<string> m_queue;
  private StreamWriter m_writer;

  public CCR() {
    m_queue = new Queue<string>();
    m_writer = new StreamWriter(string.Format("Log_{0}.txt", DateTime.Now.ToFileTime()));
  }

  public void ExceptionHandler(Exception ex, string location) {
    string item = string.Format("{0:u}: {1}\r\n\t\t{2}", DateTime.Now, location, ex.Message);
    if (ex.InnerException == null) {
      m_queue.Enqueue(item);
    } else {
      m_queue.Enqueue(item + string.Format("\r\n\t\tInner Exception: {0}", ex.InnerException.Message));
    }
    QueueHandler();
  }

  private void QueueHandler() {
    while (0 < m_queue.Count) {
      m_writer.WriteLine(m_queue.Dequeue());
    }
  }

  public void Close() {
    QueueHandler();
    m_writer.Flush();
    m_writer.Close();
    m_writer.Dispose();
  }

只要确保Close()在代码退出之前调用

于 2013-03-28T14:50:10.453 回答