我不确定在这种情况下使用什么。
我有一个asp.net web api方法基本上可以做到这一点
但是,由于我需要存储一些foursquare信息以链接到该位置的唯一数据,因此我决定将所有信息存储在我的数据库中,并让我的数据库充当我的缓存系统。
这意味着我必须插入到我的数据库中的任何新的兴趣点,检查它是否存在,如果是,则跳过它或如果它存在检查最后刷新日期(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 我发现this post向我展示了如何为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;
}
答案 0 :(得分:4)
我建议您使用async
/ await
。更新缓存是极少数情况下可以接受从ASP.NET请求提前返回的情况之一。您可以查看我的blog post on the subject以获取一些有用的代码。
所以,像这样(简化为每个位置只查找一个“有趣的地方”):
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缓存系统,而不是“自己动手”缓存。