Prerequisites:
上下文:尝试运行单元测试,但遇到某种类型的线程阻止程序。代码只需停止执行
value = await getDataToCacheAsync.Invoke();可以调试的最后一行是
return () => new Task<string?>(() => cacheValue [there]);Q:看起来出现了某种死锁,但我不清楚为什么和如何解决它
单元测试:
[Test]
public async Task GetCachedValueAsync_WithDedicatedCacheKey_ReturnsExpectedCacheValue()
{
const string cacheKey = "test-cache-key";
const string cacheValue = "test-cache-key";
var result = await _sut.GetCachedValueAsync(cacheKey, GetDataToCacheAsync(cacheValue));
Assert.AreEqual(cacheValue, result);
}
private static Func<Task<string?>> GetDataToCacheAsync(string cacheValue)
{
return () => new Task<string?>(() => cacheValue);
}测试中的代码:
public async Task<T?> GetCachedValueAsync<T>(string cacheKey, Func<Task<T?>> getDataToCacheAsync)
where T : class
{
// [Bloked here, nothing happens then, I'm expecting that it should return "test-cache-value"]
value = await getDataToCacheAsync.Invoke(); [Blocked]
...
return value
}发布于 2022-05-08 13:48:28
之后
return () => new Task<string?>(() => cacheValue [there]);
被替换为
return () => Task.FromResult(cacheValue);它开始工作了
UPD:
在这种情况下(例如Task.Run(.)、TaskFactory .等等)。
Task.FromResult返回已完成的任务并给出结果
发布于 2022-05-08 22:28:35
通常,正如在文档中所写的,您应该尽量避免通过构造函数创建任务:
此构造函数只应在需要将任务的创建和启动分开的高级场景中使用。 与调用此构造函数不同,实例化
Task对象并启动任务的最常见方法是调用静态Task.Run(Action)或TaskFactory.StartNew(Action)方法。
问题是构造函数创建的任务是“冷”任务(根据指导方针,您应该避免从方法返回“冷”任务,只返回“热”任务)--它没有启动,所以await将导致无休止的等待(实际上这里不会发生死锁)。
修复此代码有多种方法,例如:
Task.Runreturn () => Task.Run(() => cacheValue);Start方法时,要显式指定调度程序。否则,任务将安排在环境TaskScheduler.Current上,这可能是一些问题的根源):return () =>
{
var task = new Task<string?>(() => cacheValue);
task.Start();
return task;
}return () => Task.FromResult(cacheValue);https://stackoverflow.com/questions/72161495
复制相似问题