背景:
我正在使用XNA并拥有一个清单处理器,它将整理我的内容项目中的所有资产,并根据(除其他事项)对其构建类型进行分类。要做到这一点,我需要建立它们。其中一些资产有一个处理器本身使用清单,这意味着资产处理器试图调用清单处理器,所以我得到永无止境的递归。
问题:
我尝试使用一个名为Mutex
来检测项目构建何时递归并抛出错误,该错误在其他地方处理,但它不起作用。
代码:
public class ManifestProcessor : ContentProcessor<ContentManifestAsset, ContentManifestContent>
{
private static Mutex _LockingMutex = new Mutex(false, "ManifestProcessor");
public override ContentManifestContent Process(ContentManifestAsset input, ContentProcessorContext context)
{
// If we've already locked on this object then we're doing a build as a result of building some other asset, so throw an exception
if (!_LockingMutex.WaitOne(0))
{
throw new NestedManifestBuildException();
}
else
{
try
{
// Stuff that might cause this method to get
// invoked again (via reflection)
}
finally
{
_LockingMutex.ReleaseMutex();
}
}
我是否正确使用Mutex类?如何检测递归调用Process
?
答案 0 :(得分:0)
我会尝试实现一种方法来跟踪正在构建的内容以检测递归。缓存还将提高构建性能,因为Manifest可以聚合已构建的资产。请研究使用Mediator Pattern将资产与清单分离。
样品:
public class ManifestProcessor : ContentProcessor<ContentManifestAsset, ContentManifestContent>
{
private static readonly Dictionary<string, ContentManifestContent> BuildCache = new Dictionary<string, ContentManifestContent>();
public override ContentManifestContent Process(ContentManifestAsset input, ContentProcessorContext context)
{
ContentManifestContent content;
if(!BuildCache.TryGetValue(input.Name, out content))
{
VerifyStackIntegrity(context, input.Name);
content = Build(input, context);
BuildCache.Add(input.Name, content);
context.BuildStack.Pop();
}
return content;
}
private static void VerifyStackIntegrity(ContentProcessorContext context, string buildStep)
{
if(context.BuildStack.Count(x => x == buildStep) > 1)
throw new CircularBuildException();
context.BuildStack.Push(buildStep);
}
private static ContentManifestContent Build(ContentManifestAsset input, ContentProcessorContext context)
{
// build steps for Manifest/Assets/Recursion
}
}
如果你想防止递归周期,那么最简单的方法是添加一个标志。
public class ManifestProcessor : ContentProcessor<ContentManifestAsset, ContentManifestContent>
{
private static bool InProgress = false;
public override ContentManifestContent Process(ContentManifestAsset input, ContentProcessorContext context)
{
if(InProgress) throw new InProgressBuildException();
InProgress = true;
return Build(input, context);
}
private static ContentManifestContent Build(ContentManifestAsset input, ContentProcessorContext context)
{
ContentManifestContent content;
// build steps for Manifest/Assets/Recursion
InProgress = false;
return content;
}
}