Async GetAwaiter() throwing an odd exception

时间:2016-07-11 19:07:23

标签: c# asp.net asp.net-core .net-core asp.net-core-1.0

Below I have pasted some code. On the first line of the body I call an awaitable call Task<IEnumerable<SkuGcn>> GetSkuGcnList(); On the last line, in the mapPromise.GetAwaiter() it throws when getting the result with this exception:

An exception of type 'System.IO.FileNotFoundException' occurred in System.Private.CoreLib.ni.dll but was not handled in user code

Additional information: Could not load file or assembly 'System.Runtime.Serialization.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.

I know my service that the GetSkuGcnList() call is calling to, is being called, because I can set a break point and I break at it when the call is made. Then the service seems to return.

This code worked just fine with ASP.NET 5 RC1 but now not so good in ASP.Net Core 1.0 Release.

Any help will be greatly appreciated!

        public ProductItemsCacheStore(IItemsProductCacheRepository itemsRepo, IProductAvailabilityPricing proxyGoliathApi,
        IProductItemListRepo itemsListsRepo, IItemPricesCacheRepo itemPricesRepo)
        {
            var mapPromise = proxyGoliathApi.GetSkuGcnList();
            _items = itemsRepo.GetAllProductOrderListForCache();
            _itemsLists = itemsListsRepo.GetItemListsForCache();
            _priceZones = itemPricesRepo.GetAllPriceZonesAndItemPrices();
            MergeProductsWithGcn(_items, mapPromise.GetAwaiter().GetResult());
        }

My project.json looks like this:

{
  "version": "1.0.0-alpha.1",
  "description": "AvailabilityPricingClient Class Library",
  "authors": [ "irving.lennert" ],
  "packOptions": {
    "tags": [ "" ],
    "projectUrl": "",
    "licenseUrl": ""
  },

  "tooling": {
    "defaultNamespace": "AvailabilityPricingClient"
  },

  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.0",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Logging": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.Extensions.Logging.Debug": "1.0.0",
    "Microsoft.AspNet.WebApi.Client": "5.2.3"
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  }
}

The implementation of GetSkuGcnList() is this:

    public async Task<IEnumerable<SkuGcn>> GetSkuGcnList()
    {
        HttpResponseMessage response = _client.GetAsync("/api/skuGcnList").Result;

        if (response.IsSuccessStatusCode)
        {
            var skuGcns = await response.Content.ReadAsAsync<IEnumerable<SkuGcn>>();
            return skuGcns;
        }

        return null;
    }

2 个答案:

答案 0 :(得分:4)

我已经确定我正在调用的程序集无法正常运行ASP.Net Core版本。如果您查看上面的project.json就是这一行:

"Microsoft.AspNet.WebApi.Client": "5.2.3"

我已将该行更改为此行:

"System.Net.Http": "4.1.0" 

此程序集不公开相同的API,因此我必须将实现代码更改为:

    public async Task<IEnumerable<SkuGcn>> GetSkuGcnList()
    {
        HttpResponseMessage response = _client.GetAsync("/api/skuGcnList").Result;

        if (response.IsSuccessStatusCode)
        {
            var skuGcns = await response.Content.ReadAsStringAsync()
                .ContinueWith<IEnumerable<SkuGcn>>(getTask =>
                {
                    return JsonConvert.DeserializeObject<IEnumerable<SkuGcn>>(getTask.Result);
                });
            return skuGcns;
        }

        return null;
    }

此解决方案运行良好。重要的是要注意我在帖子上也有同样的问题而且它们有点复杂,所以我会提供另一个电话,我发布的帖子适合任何感兴趣的人。

    public async Task<IEnumerable<Availablity>> GetAvailabilityBySkuList(IEnumerable<string> skuList)
    {
        var output = JsonConvert.SerializeObject(skuList);
        HttpContent contentPost = new StringContent(output, System.Text.Encoding.UTF8, "application/json");
        HttpResponseMessage response = _client.PostAsync("/api/availabilityBySkuList", contentPost).Result;

        if (response.IsSuccessStatusCode)
        {
            var avail = await response.Content.ReadAsStringAsync()
                .ContinueWith<IEnumerable<Availablity>>(postTask =>
                {
                    return JsonConvert.DeserializeObject<IEnumerable<Availablity>>(postTask.Result);
                });
            return avail;
        }

        return null;
    }

感谢所有贡献!

答案 1 :(得分:1)

正如评论中提到的@DaniDev,建议不要混用同步和异步代码。关于这个主题的规范性文章是Stephen Cleary的Don't Block on Async Code

使代码异步,这有点棘手,因为您在构造函数和constructors can't be async中调用异步操作。

重构代码的一种方法是拆分构造函数(依赖注入)和初始化(异步调用)代码:

public class ProductItemsCacheStore
{
    private readonly IItemsProductCacheRepository _itemsProductCacheRepo;
    private readonly IProductAvailabilityPricing _productAvailabilityPricing;
    private readonly IProductItemListRepo _productItemListRepo;
    private readonly IItemsPricesCacheRepo _itemsPricesCacheRepo;

    private bool _initialized = false;

    public ProductItemsCacheStore(
        IItemsProductCacheRepository itemsRepo,
        IProductAvailabilityPricing proxyGoliathApi,
        IProductItemListRepo itemsListsRepo,
        IItemPricesCacheRepo itemPricesRepo)
    {
        _itemsProductCacheRepo = itemsRepo;
        _productAvailabilityPricing = proxyGoliathApi;
        _productItemListRepo = itemsListsRepo;
        _itemsPricesCacheRepo = itemsPricesRepo
    }

    public async Task Initialize()
    {
        // Could possibly move these to the constructor as well
        var _items = itemsRepo.GetAllProductOrderListForCache();
        var _itemsLists = itemsListsRepo.GetItemListsForCache();
        var _priceZones = itemPricesRepo.GetAllPriceZonesAndItemPrices();

        MergeProductsWithGcn(_items, await _productAvailabilityPricing.GetSkuGcnList());

        _initialized = true;
    }
}

您的消费代码(无论您以前在哪里构建new ProductItemsCacheStore(...))现在看起来像:

var productItemsCacheStore = new ProductItemsCacheStore(/* dependencies */);
await productItemsCacheStore.Initialize();

当然,这意味着您的消费代码也必须是异步的。它是async all the way up