【问题标题】:Unable to await method in ASP.NET (4.6) MVC5 project无法等待 ASP.NET (4.6) MVC5 项目中的方法
【发布时间】:2015-07-17 08:23:59
【问题描述】:

我目前看到一个问题,即我的 await 方法只是挂起,导致响应只是挂起,在我终止请求之前什么都不做。这在 Chrome 调试工具和 Fiddler 中都很明显。

我定义了以下 API 操作:

[Route("state/{stateCode}")]
[LogApiCallFilter]
public async Task<IList<MapPlaceDTO>> GetWithinState(string stateCode)
{

    //    
    // Additional code truncated for SO
    // Via debugging I know that the 'state' variable below is correct
    //

    IList<Place> places = await _placeManager.GetPlacesInState(state);

    // Instantiate the list of places.
    IList<MapPlaceDTO> mapPlaces = new List<MapPlaceDTO>();

    // Iterate through the places and add to the map place list
    foreach (Place place in places)
    {
        mapPlaces.Add(MapPlaceDTO.FromPlace(place));
    }

    return mapPlaces;

}

当我在调试模式下单步执行该代码以对 GetWithinState 操作进行单元测试时,IList&lt;Place&gt; places = await _placeManager.GetPlacesInState(state); 方法无异常运行,但是我无法将鼠标悬停在 places 变量上进行检查,没有任何反应。我也无法将其添加到监视列表中,我收到以下消息: error CS0103: The name 'places' does not exist in the current context

然而,有趣的是,如果我在 Web API 项目之外的“PlaceManager”单元测试中运行完全相同的代码,测试运行良好,我可以检查 places 变量。

[Fact(DisplayName = "Can_Get_All_Places_Within_State")]
[Trait("Category", "Place Manager")]
public async Task Can_Get_All_Places_Within_State()
{

    State state = new State()
    {
        ShortName = "VIC",
        Name = "Victora",
        CountryCode = "AU"
    };

    IList<Place> places = await _placeManager.GetPlacesInState(state);

    Assert.NotNull(places);
    Assert.True(places.Count > 0);

}

这是在PlaceManager.GetPlacesInState 方法中运行的代码:

public async Task<IList<Place>> GetPlacesInState(State state)
{
    if (state == null)
    {
        throw new ArgumentNullException("state", "The 'state' parameter cannot be null.");
    }

    // Build the cache key
    string cacheKey = String.Format("places_state_{0}", state.Id);

    // Get the places from the cache (if they exist)
    IList<Place> places = CacheManager.GetItem<IList<Place>>(cacheKey);

    // Get the places from the database.
    if (places == null)
    {
        // Get the places from the database
        places = await _repository.Find(i => i.State.ToLower() == state.ShortName.ToLower() && i.Country.ToLower() == state.CountryCode.ToLower());

        // If there are places, then add to the cache for next time
        if (places != null && places.Count > 0)
        {
            CacheManager.AddItem(cacheKey, places);
        }
    }

    // return the places
    return (places != null ? places : new List<Place>());
}

有谁知道为什么这可能会在 API 方法中发生,但在单元测试中运行良好?

【问题讨论】:

  • 挂起时中断并检查所有线程。 93% Find 实际上不是真正的异步方法和某种 getDataAsync().Result; 代码上的死锁
  • 这正是原因。我的 Place 对象有一个 get only 属性,它可以通过以下方式从异步函数中获取地点类型:get { return getPlaceType().Result; }。我想我需要进一步阅读 async/await 和 .Result 属性。干杯,贾斯汀。
  • 这里是阅读的起点-stackoverflow.com/questions/13140523/…

标签: c# asp.net unit-testing asp.net-web-api async-await


【解决方案1】:

正如上面 Alexei Levenkov 所提到的,我使用 getDataAsync().Result 代码导致了死锁。

在将我的 Place 对象映射到 MapPlaceDTO 对象时,Place 对象有一个 get 属性来加载 place 类型,这将通过以下方式调用异步函数:

public PlaceType PlaceType
{
    get
    {
        return getPlaceType().Result;
    }
}

一旦我删除了该属性并直接使用 await 关键字调用 GetPlaceType 方法,一切都开始正常工作。谢谢阿列克谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多