我应该在这里使用什么?线程?异步?

时间:2022-09-10 23:35:11

I am not sure what to use in this scenario.

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

I have an asp.net web api method that basically does this

我有一个asp.net web api方法,基本上这样做

  1. Finds points of interests from foursquare near user.
  2. 从foursquare附近的用户中找到兴趣点。
  3. Uses the foursquare locations to do queries in my database to find unique data about point of interest near user.
  4. 使用foursquare位置在我的数据库中进行查询,以查找有关用户附近兴趣点的唯一数据。

However since I need to store some of the foursquare information to link to my unique data to that location I decided to store all the information in my database and have my database act as my caching system.

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

This means anything new point of interest that comes in I have to insert into my database, check if it exists and if so then skip it or if it exists check the last refresh date(foursquare policy states all data must be refreshed after 30 day) and if it out past the refresh date I have to update the data.

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

I want to slow the user down and have to wait for the above to happen. I want my code to do step 1 and then do what I just mentioned while at the same time doing step 2.

我想让用户放慢速度,不得不等待上述情况发生。我希望我的代码执行第1步,然后执行我刚才提到的操作,同时执行第2步。

Once step 2 finishes I want to return the data and let the user get on their way. If my caching system is not finished then it should keep going but not bog down the user.

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

I won't use any of these new results in step 2 as if I am inserting it then I won't have any data on that location at this time.

我不会在步骤2中使用任何这些新结果,就像我插入它一样,那时我将不会在该位置上有任何数据。

Not sure if I need to make a thread or use the async/await to achieve this.

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

Edit

编辑

Here is what I am trying to do

这是我想要做的

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);
    }
}

Edit 2

编辑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);
                         }
                     }
              );
}

gives me this error

给了我这个错误

Cannot await 'RestSharp.RestRequestAsyncHandle'

I also don't get the difference between Task and void. From what I read if you just use Task it means you are sending nothing back of meaning, then why not just use void?

我也没有区分Task和void。从我读到的,如果你只是使用任务它意味着你没有发回任何意义,那么为什么不只是使用void?

Edit 2 I found this post to show me how to make the wrapper for Restsharp. It is not 100% what I want but that is a separate issue.

编辑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;
 }

When I watch from the debugger it looks like it is still all going in order. I think product and allStores need to be since I need the product before I can find the stores but PointsOfInterestNearUser should be going at the same time as FindProduct.

当我从调试器中观察时,看起来它仍然按顺序排列。我认为产品和allStores需要,因为我需要产品才能找到商店,但PointsOfInterestNearUser应该与FindProduct同时进行。

Edit 3 Here is my FindProduct Method. Not sure what to make async to me it looks like everything needs to wait.

编辑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;
    }

Edit 4

编辑4

Still not sure how to do the Task.WhenAll()

仍然不确定如何做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;
     }

1 个解决方案

#1


4  

I would recommend using async/await for this. Updating a cache is one of the rare situations where returning early from an ASP.NET request is acceptable. You can see my blog post on the subject for some helpful code.

我建议使用async / await。更新缓存是极少数情况下可以接受从ASP.NET请求提前返回的情况之一。您可以在主题上查看我的博客文章,了解一些有用的代码。

So, something like this (simplified to just look up one "interesting place" per location):

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

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;
}

You may also want to consider extending the ASP.NET caching system rather than doing a "roll your own" cache.

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

#1


4  

I would recommend using async/await for this. Updating a cache is one of the rare situations where returning early from an ASP.NET request is acceptable. You can see my blog post on the subject for some helpful code.

我建议使用async / await。更新缓存是极少数情况下可以接受从ASP.NET请求提前返回的情况之一。您可以在主题上查看我的博客文章,了解一些有用的代码。

So, something like this (simplified to just look up one "interesting place" per location):

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

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;
}

You may also want to consider extending the ASP.NET caching system rather than doing a "roll your own" cache.

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