首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Func不工作&在测试执行期间阻塞

问Func不工作&在测试执行期间阻塞
EN

Stack Overflow用户
提问于 2022-05-08 13:31:06
回答 2查看 75关注 0票数 0

Prerequisites:

  1. .Net 6.0
  2. C# 10
  3. NUnit 3.13.3

上下文:尝试运行单元测试,但遇到某种类型的线程阻止程序。代码只需停止执行

代码语言:javascript
复制
value = await getDataToCacheAsync.Invoke();

可以调试的最后一行是

代码语言:javascript
复制
return () => new Task<string?>(() => cacheValue [there]);

Q:看起来出现了某种死锁,但我不清楚为什么和如何解决它

单元测试:

代码语言:javascript
复制
[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);
}

测试中的代码:

代码语言:javascript
复制
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
}
EN

回答 2

Stack Overflow用户

发布于 2022-05-08 13:48:28

之后

return () => new Task<string?>(() => cacheValue [there]);

被替换为

代码语言:javascript
复制
return () => Task.FromResult(cacheValue);

它开始工作了

UPD:

在这种情况下(例如Task.Run(.)、TaskFactory .等等)。

Task.FromResult返回已完成的任务并给出结果

票数 2
EN

Stack Overflow用户

发布于 2022-05-08 22:28:35

通常,正如在文档中所写的,您应该尽量避免通过构造函数创建任务:

此构造函数只应在需要将任务的创建和启动分开的高级场景中使用。 与调用此构造函数不同,实例化Task对象并启动任务的最常见方法是调用静态Task.Run(Action)或TaskFactory.StartNew(Action)方法。

问题是构造函数创建的任务是“冷”任务(根据指导方针,您应该避免从方法返回“冷”任务,只返回“热”任务)--它没有启动,所以await将导致无休止的等待(实际上这里不会发生死锁)。

修复此代码有多种方法,例如:

  1. 使用Task.Run
代码语言:javascript
复制
return () => Task.Run(() => cacheValue);
  1. 手动启动创建的任务(尽管在本例中没有理由这样做。同样,正如@西奥多·祖利亚斯 - 建议所指出的,在调用Start方法时,要显式指定调度程序。否则,任务将安排在环境TaskScheduler.Current上,这可能是一些问题的根源):
代码语言:javascript
复制
return () => 
{ 
    var task = new Task<string?>(() => cacheValue); 
    task.Start(); 
    return task;
}
  1. 返回一个已完成的任务(我认为这是本例中最好的方法,除非您正在测试一个非常具体的场景):
代码语言:javascript
复制
return () => Task.FromResult(cacheValue);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72161495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档