c# - 为什么这个 MVC 方法不能以并行方式运行?
问题描述
背景
我有一个 MVC 5 应用程序,想测试请求是否并行运行。为此,我使用了下面的代码,并打开了多个发出相同请求的页面。
代码
下面是一个相对简单的方法,我想要并行性。
public async Task<ActionResult> Login(string returnUrl, string message = "")
{
var rng = new Random();
var wait = rng.Next(3, 10);
var threadGuid = Guid.NewGuid();
DebugHelper.WriteToDebugLog($"Thread {threadGuid} about to wait {wait} seconds");
await Task.Delay(wait * 1000);
DebugHelper.WriteToDebugLog($"Thread {threadGuid} finished");
return View();
}
该类DebugHelper
仅用于我可以安全地写入文件。
public static class DebugHelper
{
private static readonly object WriteLock = new object();
public static void WriteToDebugLog(string message, string path = "C:\\Temp\\Log.txt")
{
lock (WriteLock)
{
File.AppendAllLines(path, new string[] { "", GetDateString(), message });
}
}
}
输出
我一直得到这种类型的输出,这表明线程相互阻塞。
2020-03-24T13:43:43.1431913Z
Thread 6e42a6c5-d3cb-4541-b8aa-34b290952973 about to wait 7 seconds
2020-03-24T13:43:50.1564077Z
Thread 6e42a6c5-d3cb-4541-b8aa-34b290952973 finished
2020-03-24T13:43:50.1853278Z
Thread 90923f55-befd-4224-bdd8-b67f787839fc about to wait 4 seconds
2020-03-24T13:43:54.1943271Z
Thread 90923f55-befd-4224-bdd8-b67f787839fc finished
2020-03-24T13:43:54.2312257Z
Thread fa2d8d30-b762-4262-b188-0b34da5f4f04 about to wait 3 seconds
2020-03-24T13:43:57.2370556Z
Thread fa2d8d30-b762-4262-b188-0b34da5f4f04 finished
2020-03-24T13:43:57.2679690Z
Thread 37311a0e-d19e-4563-b92a-5e5e3def379a about to wait 8 seconds
2020-03-24T13:44:05.2812367Z
Thread 37311a0e-d19e-4563-b92a-5e5e3def379a finished
问题
为什么会出现这种情况?
我的印象是任何 ASP.NET 应用程序一开始都是多线程的,所以即使在我没有async/await
设置的情况下,我认为它会同时运行这些线程。
更新
正如答案/评论中所建议的,我的方法是错误的。使用以下代码后,我可以在日志中非常清楚地看到它确实在并行运行。
var targetTime = DateTime.UtcNow + TimeSpan.FromSeconds(5);
while(DateTime.UtcNow < targetTime)
{
DebugHelper.WriteToDebugLog($"Thread {threadGuid} with ID {threadId} doing stuff");
await Task.Delay(1000);
}
解决方案
它简单地归结为这样一个事实,即您的调试日志记录及其WriteLock
同步 File.AppendAllLines
强制同步锁定到所有调用它的异步函数上。
您最好有一个异步写入到调试过程,这将允许您的任务继续运行。
产品/消费者模式、信号量、事件、异步文件访问 API 的使用都浮现在脑海中。
推荐阅读
- docker - 如何将此 gitlab yml 文件重写为 docker 文件
- javascript - 防止 rxjs 主题完成
- c# - 我可以告诉外部函数从其本地函数内部返回吗?
- ruby-on-rails - 如何创建 CSV 并将其保存到 Rails 中的主机?
- python - 无法从 arduino 获取 gps 坐标以与 kivy mapview 绑定
- asp.net-mvc - IIS 从错误的位置读取.. 是吗?
- replication - Gerrit 3.0.4 如何删除已提交但复制失败的提交
- service-worker - 如果未访问,chrome 是否会删除离线内容?
- ios - IOS下OpenGL如何正确渲染广色域(Display p3)
- python - 将模板变量插入块标签