首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用RazorEngine并发解析Razor模板

使用RazorEngine并发解析Razor模板
EN

Stack Overflow用户
提问于 2011-06-23 01:51:58
回答 1查看 13.5K关注 0票数 15

我在一个MVC3Web应用程序中使用Razor库(http://razorengine.codeplex.com/),通过RazorEngine模板语言解析字符串(不是视图)。

一般而言,这样做效果很好。但是,当多个用户同时访问解析Razor模板的代码时,我偶尔会看到内部Razor编译器中出现的错误(请参阅下面的两个错误)。我在解释这些错误时遇到了麻烦,但我猜我调用Razor编译器的方式并不安全。

这是Razor编译器的已知问题吗?普通的剃刀视图(.cshtml)怎么不会遇到这个问题呢?有没有比将我的应用程序对Razor.Parse的所有调用都包装在互斥锁中更好的解决方法呢?

我的调用代码如下所示,只是一个简单的Razor.Parse包装器

代码语言:javascript
复制
    protected string ParseTemplate<T>(string templateString, T model)
    {
        //This binderAssembly line is required by NUnit to prevent template compilation errors
        var binderAssembly = typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly;
        var result = Razor.Parse(templateString, model);
        return result;
    }

错误一:

代码语言:javascript
复制
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: chunkLength
at System.Text.StringBuilder.ToString()
at System.Web.Razor.Generator.RazorCodeGenerator.BlockContext.MarkEndGeneratedCode()
at System.Web.Razor.Generator.RazorCodeGenerator.WriteBlock(BlockContext block)
at System.Web.Razor.Parser.ParserContext.FlushNextOutputSpan()
at System.Web.Razor.Parser.ParserContext.StartBlock(BlockType blockType, Boolean outputCurrentBufferAsTransition)
at System.Web.Razor.Parser.ParserBase.ParseComment()
at System.Web.Razor.Parser.ParserBase.TryParseComment(SpanFactory previousSpanFactory)
at System.Web.Razor.Parser.ParserBase.ParseBlockWithOtherParser(SpanFactory previousSpanFactory, Boolean collectTransitionToken)
at System.Web.Razor.Parser.HtmlMarkupParser.TryStartCodeParser(Boolean isSingleLineMarkup, Boolean documentLevel)
at System.Web.Razor.Parser.HtmlMarkupParser.ParseRootBlock(Tuple`2 nestingSequences, Boolean caseSensitive)
at System.Web.Razor.Parser.RazorParser.Parse(LookaheadTextReader input, ParserVisitor visitor)
at System.Web.Razor.RazorTemplateEngine.GenerateCodeCore(LookaheadTextReader input, String className, String rootNamespace, String sourceFileName, Nullable`1 cancelToken)
at System.Web.Razor.RazorTemplateEngine.GenerateCode(TextReader input, String className, String rootNamespace, String sourceFileName, Nullable`1 cancelToken)
at System.Web.Razor.RazorTemplateEngine.GenerateCode(TextReader input)
at RazorEngine.Compilation.CompilerServiceBase.GetCodeCompileUnit(String className, String template, ISet`1 namespaceImports, Type templateType, Type modelType)
at RazorEngine.Compilation.DirectCompilerServiceBase.Compile(TypeContext context)
at RazorEngine.Compilation.DirectCompilerServiceBase.CompileType(TypeContext context)
at RazorEngine.Templating.TemplateService.CreateTemplate(String template, Type modelType)
at RazorEngine.Templating.TemplateService.Parse[T](String template, T model, String name)
at RazorEngine.Razor.Parse[T](String template, T model, String name)

错误二:

代码语言:javascript
复制
System.ObjectDisposedException: Cannot read from a closed TextReader.
at System.IO.StringReader.Read()
at System.Web.Razor.Text.BufferingTextReader.NextCharacter()
at System.Web.Razor.Text.BufferingTextReader.Read()
at System.Web.Razor.Parser.ParserContext.AcceptCurrent()
at System.Web.Razor.Parser.HtmlMarkupParser.ParseRootBlock(Tuple`2 nestingSequences, Boolean caseSensitive)
at System.Web.Razor.Parser.RazorParser.Parse(LookaheadTextReader input, ParserVisitor visitor)
at System.Web.Razor.RazorTemplateEngine.GenerateCodeCore(LookaheadTextReader input, String className, String rootNamespace, String sourceFileName, Nullable`1 cancelToken)
at System.Web.Razor.RazorTemplateEngine.GenerateCode(TextReader input, String className, String rootNamespace, String sourceFileName, Nullable`1 cancelToken)
at System.Web.Razor.RazorTemplateEngine.GenerateCode(TextReader input)
at RazorEngine.Compilation.CompilerServiceBase.GetCodeCompileUnit(String className, String template, ISet`1 namespaceImports, Type templateType, Type modelType)
at RazorEngine.Compilation.DirectCompilerServiceBase.Compile(TypeContext context)
at RazorEngine.Compilation.DirectCompilerServiceBase.CompileType(TypeContext context)
at RazorEngine.Templating.TemplateService.CreateTemplate(String template, Type modelType)
at RazorEngine.Templating.TemplateService.Parse[T](String template, T model, String name)
at RazorEngine.Razor.Parse[T](String template, T model, String name)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-23 02:00:44

更新:根据他们团队的blog post,最新版本3.x (on Github)现在是线程安全的。我没有检查它的线程安全性的准确性,但假设它已经被正确地实现了。请将此答案的其余部分视为仅用于历史目的。

从代码来看,这个项目看起来并不是线程安全的。

Razor.Parse

代码语言:javascript
复制
public static string Parse<T>(string template, T model, string name = null)
{
    return DefaultTemplateService.Parse<T>(template, model, name);
}

TemplateService.Parse

代码语言:javascript
复制
public string Parse<T>(string template, T model, string name = null)
{
    var instance = GetTemplate(template, typeof(T), name);
    ...
}

TemplateService.GetTemplate

代码语言:javascript
复制
internal ITemplate GetTemplate(string template, Type modelType, string name)
{
    if (!string.IsNullOrEmpty(name))
        if (templateCache.ContainsKey(name))
            return templateCache[name];

    var instance = CreateTemplate(template, modelType);

    if (!string.IsNullOrEmpty(name))
        if (!templateCache.ContainsKey(name))
            templateCache.Add(name, instance);

    return instance;
}

因此,Razor.Parse是一种静态方法。DefaultTemplateServiceRazor上的静态属性,ParseGetTemplate是实例方法,但由于静态DefaultTemplateService,它们可以有效地静态调用。这意味着所有线程都会通过相同的实例并通过GetTemplate。您将注意到,GetTemplate在没有获取任何锁的情况下改变了状态(templateCache)。因此,此代码不是threadsafe。

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6444277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档