我编写了一个控制台应用程序,通常通过任务计划程序运行,没有用户。如果合适,它会将控制台输出重定向到恰好位于网络上的文件(名称中包含app-start timestamp)。
我见过几个案例 - 它们很少见 - 似乎文件内容过早结束(也就是说,程序生成的后续消息不存在)。第三方日志记录工具(Gibraltar Loupe)的输出向我显示,如果网络故障导致输出文件暂时不可用,则调用Console.WriteLine可能会失败,从而导致未处理的异常。
(曾经,普通应用程序的正常异常处理 - 有点显着 - 能够编写有关由于“指定的网络名称不再可用”而导致Console.WriteLine失败时导致的未处理异常的消息 - 一定是一个非常暂时的故障!)
我想不出一种方法,除了用调用我自己的东西来替换对Console.WriteLine的所有调用来捕获这些错误,等待网络再次可用,然后再次尝试。 (或者可能它会将输出重定向到本地文件以进行剩余的运行,但如果网络不可用,其他事情可能会失败。)
在具有数百个应用程序的应用程序中替换对Console.WriteLine的所有调用将导致主要的源代码更改爆炸,从而强制更改几个月内未更改的文件。我有选择吗?
是否有人对如何处理此问题有不同的建议(除了从项目开头抽象出Console.WriteLine)?
感谢您提出任何建议。
答案 0 :(得分:4)
尝试解决软件中的片状硬件问题并不是最好的主意。但请考虑:
你可能认为最后一个很有吸引力。示例代码:
using System.IO;
class MyWriter : TextWriter {
private TextWriter writer;
public MyWriter(TextWriter writer) { this.writer = writer; }
public override Encoding Encoding { get { return writer.Encoding; } }
public override void Write(char value) {
for (int delay = 1; ; delay *= 2) {
try { writer.Write(value); return; }
catch { if (delay > 3600) throw; }
System.Threading.Thread.Sleep(1000*delay);
}
}
}
class Program {
static void Main(string[] args) {
Console.SetOut(new MyWriter(Console.Out));
Console.SetError(new MyWriter(Console.Error));
// etc...
}
}
答案 1 :(得分:1)
老实说,我认为抽象出Console.WriteLine正是你想要做的。它允许您构建异常处理和重试策略,或允许您的应用程序继续处理文件再次可用时应该执行的任何操作。它也有助于UnitTesting和抽象等等。
然而,说了这么多。您可以在执行任务期间写入本地文件,然后将文件移动到网络共享。这意味着你应该能够“信任”Console.WriteLine将停止工作,这应该避免包装每个调用。然后在任务结束时,您可以将文件移动到网络位置。您可以将这个移动逻辑包装在一大堆错误处理和重试逻辑中,这些逻辑不会影响您现有的代码。