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

标签 c# multithreading mongodb asynchronous

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

我们有两个方法: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 来确保它不会被大量并行化。

最佳答案

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

对于您创建的每个任务,您都显式调用Result属性

.Result;

这会导致阻塞当前线程,直到任务完成。

如果您需要处理 Task.Complete 事件,您可以使用 continuation methodTask 类的静态方法 to 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 的很棒的文章,因此您可以尝试从那里开始。

关于c# - MongoDB 2.0 驱动程序和非异步代码的潜在死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33628713/

相关文章:

c# - 显示换行符 asp.net mvc razor

c - 关于 _mm_clflush (void const* p)

java多线程应用: getting thread blocked time

mongodb - 仅检索 MongoDB 集合中对象数组中的查询元素

Javascript:深入遍历/遍历对象键

javascript - Webbrowser控件的onclick事件

c# - 使用 Windows 编解码器解码音频文件

c# - IEnumerable.Cast() 与 IEnumerable.Select() 中的转换

java - JVM 如何确保新对象内存分配的线程安全

mongodb - mongodb 和 cassandra 的 Docker 健康检查总是失败