1

我不确定在这种情况下使用什么。

我有一个基本上可以做到这一点的 asp.net web api 方法

  1. 从用户附近的foursquare 中查找兴趣点。
  2. 使用四方位置在我的数据库中进行查询,以查找有关用户附近兴趣点的唯一数据。

但是,由于我需要存储一些四方信息以将我的唯一数据链接到该位置,因此我决定将所有信息存储在我的数据库中,并让我的数据库充当我的缓存系统。

这意味着我必须将任何新的兴趣点插入到我的数据库中,检查它是否存在,如果存在则跳过它,或者如果它存在检查最后一次刷新日期(foursquare 政策规定所有数据必须在 30 天后刷新)如果它超过了刷新日期,我必须更新数据。

我想减慢用户的速度,并且必须等待上述情况发生。我希望我的代码执行第 1 步,然后在执行第 2 步的同时执行我刚才提到的操作。

一旦第 2 步完成,我想返回数据并让用户继续前进。如果我的缓存系统没有完成,那么它应该继续运行但不会让用户陷入困境。

我不会在第 2 步中使用这些新结果中的任何一个,就好像我正在插入它一样,那么此时我在该位置将没有任何数据。

不确定我是否需要创建一个线程或使用 async/await 来实现这一点。

编辑

这是我想要做的

public HttpResponseMessage Get()
{
    // this will do a foursquare lookup to find all stores near the user
    // I want to insert them into my database and link it to my unquie data. 
    // stores pulled from foursquare will
    // a) Be new and not in my database
    // b) exist in my database but have been refreshed lately
    // c) have not been refreshed in timeframe of foursquare policy
    // THIS SHOULD WORK IN THE BACKGROUND
    storeService.PointsOfInterestNearUser(80, -130); //As you can see it is 
                        //void. Not sure where to put the async/await stuff

    // find this product. Should be happening at the same time as above line.
    var product = productService.FindProduct("Noodles");

    //This will get returned to the user. 
    // the new stores taht are being added in StoreNearUser 
    //won't effect this search as I will have not data on this new store
    // if existing store is being refreshed it is possible old 
    //address might be picked up...
    //I can live with that as I doubt the address will change much.

    // this should happen after product
    var allStores = storeService.FindStoresThatHaveItem(product);

    // this should be returned as soon as above line is finished. 
    //If StoreNearUser is not done, it should keep going but not hold up user.
    return allStores;
}
public void StoresNearUser(double latitude, double longitude)
{
    // get all categories I can about in foursquare. 
    //First time from db otherwise cached.
    List<StoreCategory> storeCategories = GetStoreCategories();

    // do a request and get everything in near the user
    //(provided it is also in a category I care about)
    var request = CreateFoursquareStoreRequest
                       (latitude, longitude, storeCategories);

    // do the actual call.
    var response = client.Execute<VenueSearch>(request);


    if (response.StatusCode == System.Net.HttpStatusCode.OK)
    {
// start going through the results, add or update or skip of entry will happen
        AddUpdateStores(storeCategories, response);
    }
    else
    {
        ErrorSignal.FromCurrentContext().Raise(response.ErrorException);
    }
}

编辑 2

public async Task StoresNearUser(double latitude, double longitude)
{
// get all categories I can about in foursquare. First time from db otherwise cached.
    List<StoreCategory> storeCategories = GetStoreCategories();

// do a request and get everything in near the user(provided it is also in a category I care about)
    var request = CreateFoursquareStoreRequest(latitude, longitude, storeCategories);

    await client.ExecuteAsync<VenueSearch>
              (  request
                 , response =>
                     {
                         if (response.StatusCode == System.Net.HttpStatusCode.OK)
                         {
                             AddUpdateStores(storeCategories, response);
                         }
                         else
                         {
                             ErrorSignal.FromCurrentContext()
                                        .Raise(response.ErrorException);
                         }
                     }
              );
}

给我这个错误

Cannot await 'RestSharp.RestRequestAsyncHandle'

我也不明白 和 之间的Task区别void。从我读到的,如果你只是使用Task它意味着你没有发送任何意义,那么为什么不直接使用void呢?

编辑 2 我发现这篇文章向我展示了如何为 Restsharp 制作包装器。这不是我想要的 100%,但这是一个单独的问题。

public async Task StoresNearUser(double latitude, double longitude)
{
    List<StoreCategory> storeCategories = GetStoreCategories();

    var request = CreateFoursquareStoreRequest
                    (latitude, longitude, maxRadius, returnLimit, storeCategories);

    var response =  await client.GetResponseAsync(request);

    if (response.StatusCode == HttpStatusCode.OK)
    {
// had to use json.net right now as the wrapper does not expose restsharps deserilizer
        var venue = JsonConvert
                    .DeserializeObject<VenueSearch>(response.Content);
        AddUpdateStores(storeCategories, venue);
    }
    else
    {
        ErrorSignal.FromCurrentContext()
                   .Raise(response.ErrorException);
    }
}

public async Task<HttpResponseMessage>Get()
{
    await storeService.PointsOfInterestNearUser(80, -130);
    var product = productService.FindProduct("Noodles");
    var allStores = storeService.FindStoresThatHaveItem(product);
    return allStores;
 }

当我从调试器中观察时,它看起来仍然一切正常。我认为product并且allStores需要,因为我需要产品才能找到商店,但PointsOfInterestNearUser应该与FindProduct.

编辑 3 这是我的 FindProduct 方法。不知道要做什么让我异步看起来一切都需要等待。

public ResponseResult<Product> FindProduct(string barcode)
    {
        ResponseResult<Product> responseResult = new ResponseResult<Product>();
        Product product = null;

        try
        {

            var findBarCode = context.Barcodes.Where(x => x.Code == barcode).Select(x => x.Product).FirstOrDefault();

            responseResult.Response = product;

            if (product == null)
            {
                responseResult.Status.Code = HttpStatusCode.NotFound;
            }
            else
            {
                responseResult.Status.Code = HttpStatusCode.OK;
            }
        }
        catch (SqlException ex)
        {
            ErrorSignal.FromCurrentContext().Raise(ex);
            responseResult.Status.Code = HttpStatusCode.InternalServerError;
            responseResult.Status.Message = GenericErrors.InternalError;
        }

        return responseResult;
    }

编辑 4

仍然不确定如何执行 Task.WhenAll()

 public async Task<HttpResponseMessage>Get()
    {
      Task[] tasks = new Task[2];
      tasks[0] = storeService.PointsOfInterestNearUser(80, -130);
      tasks[1] = productService.FindProduct("Noodles");

       await Task.WhenAll(tasks);

       // not sure how to get product back out. I looked in the debugger and saw a "Result" that has it but when I do tasks[1].Result inetllisene cannot find .Result
       var allStores = storeService.FindStoresThatHaveItem(product);
       return allStores;
     }
4

1 回答 1

4

我建议为此使用async/ await。更新缓存是可以接受从 ASP.NET 请求提前返回的罕见情况之一。您可以查看我关于该主题的博客文章以获取一些有用的代码。

所以,像这样(简化为每个位置只查找一个“有趣的地方”):

public async Task<PlaceWithData> FindPlaceAsync(Location myLocation)
{
  Place place = await GetPlaceFromFoursquareAsync(myLocation);
  PlaceWithData ret = await GetExtraDataFromDatabaseAsync(place);
  if (ret.NeedsRefresh)
    BackgroundTaskManager.Run(() => UpdateDatabaseAsync(place, ret));
  return ret;
}

您可能还想考虑扩展 ASP.NET 缓存系统,而不是“滚动您自己的”缓存。

于 2013-05-17T22:49:28.073 回答