MongoDB 2.0驱动程序和非异步代码的潜在死锁

时间:2015-11-10 11:15:07

标签: c# multithreading mongodb asynchronous

我们有一个ASP.NET MVC网站,并将所有文本存储在MongoDB中。 LocalizationTextManager类负责提供这些文本并在内部缓存它们。通常,该方法非常快(<5ms),如果结果在缓存中则更快。

我们有两个方法:GetString和GetStringAsync。 GetStringAsync是首选,但我们在Razor中使用GetString方法,或者在一些不在异步上下文中的罕见情况下使用。

MongoDB有一个异步驱动程序,我需要非同步地实现它。因此我们尝试了几种方法。我确保在代码中的任何地方设置ConfigureAwait(false)。

FindOrAddTextFromRepositoryAsync(key).Result;
Task.Run(async () => await FindOrAddTextFromRepositoryAsync(key)).Result;
Task.Run(async () => await FindOrAddTextFromRepositoryAsync(key).ConfigureAwait(false)).Result;

我知道在任务中我不需要ConfigureAwait(false)(因为不应该有同步上下文)。

我刚刚部署了网站,并在部署后挂起。几次重启后,它正在运行。我之前做了转储,发现有很多这些方法调用:

w3wp(4).DMP中的以下线程正在System.Threading.Monitor.Wait中等待。 ~100线程被阻止:

mscorlib_ni!System.Threading.ManualResetEventSlim.Wait(Int32, System.Threading.CancellationToken)+3ec 
mscorlib_ni!System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken)+db 
mscorlib_ni!System.Threading.Tasks.Task.InternalWait(Int32, System.Threading.CancellationToken)+24a 
mscorlib_ni!System.Threading.Tasks.Task`1[[System.__Canon, mscorlib]].GetResultCore(Boolean)+36 
GP.Components.Globalization.LocalizationTextManager.GetString(System.String, System.String)+2f4 
GP.Components.Globalization.LocalizationTextManager.GetString(System.String, System.Globalization.CultureInfo)+8a 

我的问题是:如何正确实施?另一个想法是使用LimitedThreadsScheduler来确保它不会大量并行化。

1 个答案:

答案 0 :(得分:1)

代码中的主要问题是您的代码不是异步的!

对于您创建的每个Task,您明确调用Result属性

.Result;

导致阻止当前线程,直到任务完成。

如果您需要处理Task.Complete event,则可以使用Taskcontinuation methodto wait the tasks are pending或静态方法。只是不要阻止你的任务:

.ContinueWith( (t) => { Console.WriteLine(t.Result); },
    TaskContinuationOptions.OnlyOnRanToCompletion);

或:

Task.WaitAll(tasks);

正如我所看到的,在跟踪GetString中,非异步版本正在运行并等待结果,因此其他线程无法执行任何操作。我建议您尝试通过setting the MaximumThreads for default thread pool调整性能Tasks,并将不同任务调度程序的同步和异步代码分开,这样它们就不会相互阻塞。其他任务选项在此处解释:Task.Run vs Task.Factory.StartNew

至于你最后的问题,这是一篇关于How to: Create a Task Scheduler That Limits Concurrency的精彩文章,所以你可以尝试从那里开始。