gpt4 book ai didi

c# - Task.WhenAll() 一次只执行 2 个线程?

转载 作者:太空狗 更新时间:2023-10-30 00:31:34 28 4
gpt4 key购买 nike

在这个问题中,我试图缓存单个值,我们称它为 foo。如果该值未缓存,则需要一段时间才能检索。

我的问题不是实现,而是测试

为了对其进行测试,我使用 Task.WhenAll() 触发了 5 个并发任务以获取缓存值。第一个进入锁并异步检索值,而其他 4 个线程应该等待锁。等待之后,他们应该一个一个地重新检查缓存的值,发现它已经被第一个缓存它的线程检索到,并且不进行第二次检索就返回它。

[TestClass]
public class Class2
{
private readonly Semaphore semaphore = new Semaphore(1, 1);

private bool? foo;

private async Task<bool> GetFoo()
{
bool fooValue;

// Atomic operation to get current foo
bool? currentFoo = this.foo;

if (currentFoo.HasValue)
{
Console.WriteLine("Foo already retrieved");
fooValue = currentFoo.Value;
}
else
{
semaphore.WaitOne();
{
// Atomic operation to get current foo
currentFoo = this.foo;

if (currentFoo.HasValue)
{
// Foo was retrieved while waiting
Console.WriteLine("Foo retrieved while waiting");
fooValue = currentFoo.Value;
}
else
{
// Simulate waiting to get foo value
Console.WriteLine("Getting new foo");
await Task.Delay(TimeSpan.FromSeconds(5));
this.foo = true;
fooValue = true;
}
}
semaphore.Release();
}

return fooValue;
}

[TestMethod]
public async Task Test()
{
Task[] getFooTasks = new[] {
this.GetFoo(),
this.GetFoo(),
this.GetFoo(),
this.GetFoo(),
this.GetFoo(),
};
await Task.WhenAll(getFooTasks);
}
}

在我的实际测试和生产代码中,我通过接口(interface)检索值并使用 Moq 模拟该接口(interface)。在测试结束时,我验证接口(interface)仅被调用 1 次(通过),而不是 > 1 次(失败)。

输出:

Getting new foo
Foo retrieved while waiting
Foo already retrieved
Foo already retrieved
Foo already retrieved

但是您可以从测试的输出中看出它并不像我预期的那样。看起来好像只有 2 个线程同时执行,而其他线程等到前两个线程完成后才进入 GetFoo() 方法。

为什么会这样?是因为我在 VS 单元测试中运行它吗?请注意,我的测试仍然通过,但不是我期望的那样。我怀疑 VS 单元测试中的线程数有一些限制。

最佳答案

Task.WhenAll() 不会启动任务 - 它只是等待它们。

同样,调用 async 方法实际上并不会强制并行化 - 它不会引入新线程或类似的东西。只有在以下情况下,您才会获得新线程:

  • 您等待尚未完成的事情,并且您的同步上下文将继续安排在新线程上(例如,它不会在 WinForms 上下文中执行;它只会重用 UI 线程)
  • 您显式使用了 Task.Run,任务调度程序创建了一个新线程来运行它。 (当然,它可能不需要。)
  • 您明确地开始了一个新线程。

老实说,在异步方法中使用阻塞 Semaphore 方法对我来说感觉很不对。您似乎并没有真正接受异步的想法...我没有尝试确切地分析您的代码将要做什么,但我认为您需要阅读更多关于如何async 的工作原理,以及如何最好地使用它。

关于c# - Task.WhenAll() 一次只执行 2 个线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24949007/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com