Markdig does not appear to be threadsafe #42

Closed
opened 2026-01-29 14:22:38 +00:00 by claunia · 2 comments
Owner

Originally created by @dotnetchris on GitHub (Jul 22, 2016).

While running inside a Parallel.ForEeach

   private readonly MarkdownPipeline _markdownPipeline = new MarkdownPipelineBuilder()
.UseEmojiAndSmiley().UseEmphasisExtras().Build();

Parallel.ForEach( =>
    Markdown.ToHtml(mytext, _markdownPipeline);

Would throw intermittent exceptions for

The character~is already used by another emphasis descriptor,
The given key was not present in the dictionary.

Given the dictionary error message, it appears somewhere you're using a dictionary where either you need to use ConcurrentDictionary or you need to copy the data.

When i switched my usage from the readonly field to

using (var localPipeline = new ThreadLocal<MarkdownPipeline>(() =>
 new MarkdownPipelineBuilder().UseEmojiAndSmiley().UseEmphasisExtras().Build()))

and closing over localPipeline.Value instead of _markdownPipeline the errors went away.

Here's a stack trace for when you have tearing that results in "the character..." error:

   at Markdig.Parsers.Inlines.EmphasisInlineParser.Initialize(InlineProcessor processor)
   at Markdig.Parsers.ParserList`2.Initialize(TState initState)
   at Markdig.Parsers.InlineParserList.Initialize(InlineProcessor initState)
   at Markdig.Parsers.InlineProcessor..ctor(StringBuilderCache stringBuilders, MarkdownDocument document, InlineParserList parsers, Boolean preciseSourcelocation)
   at Markdig.Parsers.MarkdownParser..ctor(String text, MarkdownPipeline pipeline)
   at Markdig.Parsers.MarkdownParser.Parse(String text, MarkdownPipeline pipeline)
   at Markdig.Markdown.Parse(String markdown, MarkdownPipeline pipeline)
   at Markdig.Markdown.ToHtml(String markdown, TextWriter writer, MarkdownPipeline pipeline)
   at Markdig.Markdown.ToHtml(String markdown, MarkdownPipeline pipeline)
Originally created by @dotnetchris on GitHub (Jul 22, 2016). While running inside a Parallel.ForEeach ``` c# private readonly MarkdownPipeline _markdownPipeline = new MarkdownPipelineBuilder() .UseEmojiAndSmiley().UseEmphasisExtras().Build(); Parallel.ForEach( => Markdown.ToHtml(mytext, _markdownPipeline); ``` Would throw intermittent exceptions for `The character`~`is already used by another emphasis descriptor,` `The given key was not present in the dictionary.` Given the dictionary error message, it appears somewhere you're using a dictionary where either you need to use ConcurrentDictionary or you need to copy the data. When i switched my usage from the readonly field to ``` c# using (var localPipeline = new ThreadLocal<MarkdownPipeline>(() => new MarkdownPipelineBuilder().UseEmojiAndSmiley().UseEmphasisExtras().Build())) ``` and closing over localPipeline.Value instead of _markdownPipeline the errors went away. Here's a stack trace for when you have tearing that results in "the character..." error: ``` at Markdig.Parsers.Inlines.EmphasisInlineParser.Initialize(InlineProcessor processor) at Markdig.Parsers.ParserList`2.Initialize(TState initState) at Markdig.Parsers.InlineParserList.Initialize(InlineProcessor initState) at Markdig.Parsers.InlineProcessor..ctor(StringBuilderCache stringBuilders, MarkdownDocument document, InlineParserList parsers, Boolean preciseSourcelocation) at Markdig.Parsers.MarkdownParser..ctor(String text, MarkdownPipeline pipeline) at Markdig.Parsers.MarkdownParser.Parse(String text, MarkdownPipeline pipeline) at Markdig.Markdown.Parse(String markdown, MarkdownPipeline pipeline) at Markdig.Markdown.ToHtml(String markdown, TextWriter writer, MarkdownPipeline pipeline) at Markdig.Markdown.ToHtml(String markdown, MarkdownPipeline pipeline) ```
claunia added the bug label 2026-01-29 14:22:39 +00:00
Author
Owner

@xoofx commented on GitHub (Jul 23, 2016):

Good catch, this should be fixed by commit 82af7ca
The initialization should not occur at parsing time but pipeline build time. When I switched to a Pipeline+Builder workflow, forgot to move the init code. I should take the time to cleanup a bit more this code.

@xoofx commented on GitHub (Jul 23, 2016): Good catch, this should be fixed by commit 82af7ca The initialization should not occur at parsing time but pipeline build time. When I switched to a Pipeline+Builder workflow, forgot to move the init code. I should take the time to cleanup a bit more this code.
Author
Owner

@dotnetchris commented on GitHub (Jul 26, 2016):

Awesomely fast fix

@dotnetchris commented on GitHub (Jul 26, 2016): Awesomely fast fix
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/markdig#42