具有交叉关注的循环依赖性

本文关键字:循环 依赖性 | 更新日期: 2023-09-27 18:23:52

因此,本示例旨在为我试图修改的更大系统(即Orchard CMS)提供一个简单的视图。因此,它可能并不完美。


我正在尝试创建一个通过设置进行管理的日志记录系统。我遇到的问题是,检索设置会导致日志记录。以下是一个简单的例子,有望描述这个问题:

static void Main(string[] args)
{
    string[] messages = "this is a test.  but it's going to be an issue!".Split(' ');
    Parallel.ForEach(messages, Log);
    Console.ReadLine();
}
public static void Log(string message)
{
    Console.WriteLine(GetPrefix() + message);
}
public static string GetPrefix()
{
    Log("Getting prefix!");
    return "Prefix: ";
}

这是一个明显的StackOverflowException。但是,我该如何解决?在收到GetPrefix的响应之前,我不能只禁用日志记录,因为我可能会错过日志。(事实上,在这个简单的例子中,除了第一个,我错过了所有的。)

static void Main(string[] args)
{
    string[] messages = "this is a test.  but it's going to be an issue!".Split(' ');
    Parallel.ForEach(messages, Log);
    Console.ReadLine();
}
static bool _disable = false;
public static void Log(string message)
{
    if (_disable)
    {
        return;
    }
    _disable = true;
    Console.WriteLine(GetPrefix() + message);
    _disable = false;
}
public static string GetPrefix()
{
    Log("Getting prefix!");
    return "Prefix: ";
}

(^坏。)

请注意,我目前无法控制GetPrefix方法,只能控制Log方法。

我不确定是否有办法解决这个问题;我可能需要将设置放在其他地方(例如配置或单独的设置文件)。然而,如果有人有想法或建议,我很乐意尝试任何东西,因为我更喜欢保留现在的设置(在管理界面中)。

具有交叉关注的循环依赖性

您所需要做的就是禁用当前堆栈帧。现在,您可以使用反射来遍历堆栈帧,看看它是否被调用,但有一个简单得多的方法。每个线程都有一个堆栈框架。因此,使静态变量[ThreadStatic]

[线程静态]static bool _disable=false;

这是怎么回事?

http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx

"表示静态字段的值对于每个线程都是唯一的。"

编辑:然而,光靠这一点可能还不够。您可能想要的是每个TASK一个静态变量。现在,由于任务将按线程顺序执行,在这种特殊情况下,我不认为这是一个问题,除非记录器可能在不禁用的情况下失败。。。我不确定在这种情况下会发生什么,但这可能需要你至少将事情包装在一个try/finaly块中:

static void Main() //Main(string[] args)
{
    string[] messages = "this is a test.  but it's going to be an issue!".Split(' ');
    Parallel.ForEach(messages, Log);
    Console.ReadLine();
}
[ThreadStatic]
static bool _disable = false;
public static void Log(string message)
{
    if (_disable)
    {
        return;
    }
    try {
        _disable = true;
        Console.WriteLine(GetPrefix() + message);
    } finally {
        _disable = false;
    }
}
public static string GetPrefix()
{
    Log("Getting prefix!");
    return "Prefix: ";
}

编辑二:来自http://msdn.microsoft.com/en-us/library/dd460712.aspx似乎一旦一组任务中的任何一个在任务委托之外抛出异常,就不能保证执行任何剩余任务。最好在您的代理中处理这些特殊情况。

如何将日志方法拆分为:

public static void LogWithPrefix(string message)
{
    var prefix = GetPrefix();
    Log(prefix + message);
}
public static void Log(string message)
{
    Console.WriteLine(message);
}