【发布时间】:2014-09-02 08:13:56
【问题描述】:
我最近发布了另一个关于如何处理数据库中的项目列表并在处理失败时重试 3 次的问题。
问题可以在这里找到:C# process large list of items in a loop and retry if fails
我对收到的该问题的答案进行了一些更改,代码如下:
我有一个继承 ApiController 类的抽象类,我所有的 Web Api 控制器都继承了 ApiBaseController:
在ApiBaseController 中,我定义了使用存储库模式的 UnitOfWork,以便对 SQL 数据库进行 CRUD。 UnitOfWork 和存储库模式运行良好,我已经对其进行了测试,没有任何问题。
public abstract class ApiBaseController : ApiController
{
protected UnitOfWork Uow { get; set; }
protected override void Dispose(bool disposing)
{
if (Uow != null && Uow is IDisposable)
{
((IDisposable)Uow).Dispose();
Uow = null;
}
base.Dispose(disposing);
}
}
这里我有一个JobController,它继承了ApiBaseController,它继承了ApiController,使它成为一个Web Api 控制器。
这个控制器有一个端点api/endpoint/sendrequests,当被调用时将从数据库中获取所有Jobs,并以10个为一组进行处理。
ProcessTaskAsync 方法将处理从数据库中检索到的每个单独的任务,如果失败,它将尝试再处理 2 次,直到该任务被忽略。
除了在ProcessTaskAsync 处理任务后我尝试使用UnitOfWork await Uow.Results.AddAsync(result); 将任务结果保存到数据库之外,一切都很好。这里失败了!问题是 Uow 对象为空,我不明白为什么。我在想是因为任务是异步处理的,控制器执行结束,这意味着控制器已被释放,因此 UnitOfWork。
知道为什么Uow 为空,我该如何解决?
[AllowAnonymous]
[RoutePrefix("api/endpoint")]
public class JobController : ApiBaseController
{
private const int PAGED_LIST_SIZE = 10;
private const int MAX_RETRY_COUNT = 3;
public JobController()
{
Uow = new UnitOfWork();
}
[HttpPost]
[AllowAnonymous]
[Route("sendrequests")]
public async Task<IHttpActionResult> SendRequests()
{
try
{
var items = await Uow.Jobs.GetAllAsync();
await ProcessTasks(items);
return Ok();
}
catch (Exception ex)
{
return BadRequest();
}
}
private async Task ProcessTasks(List<Job> items)
{
var pagedResults = items.Paged<Job>(PAGED_LIST_SIZE);
if (pagedResults != null && pagedResults.Count() > 0)
{
foreach (var collection in pagedResults)
{
List<Task> tasks = new List<Task>();
foreach (var item in collection.ToList())
{
var task = Task.Factory.StartNew(() => ProcessTaskAsync(item));
tasks.Add(task);
}
try
{
await Task.WhenAll(tasks.ToArray());
}
catch (Exception ez)
{
//log here the failed ones
}
}
}
}
private async void ProcessTaskAsync(Job item)
{
if (item.Processed >= MAX_RETRY_COUNT)
{
Debug.WriteLine(string.Format("Max count {0} reached for task: {1} ", item.Processed.ToString(), item.Name));
return;
}
item.Processed++;
try
{
Result result = await item.Process();
if (result != null)
{
await Uow.Results.AddAsync(result);
}
Debug.WriteLine(string.Format("working item name: {0}", item.Name));
}
catch (Exception ex)
{
Debug.WriteLine(string.Format("Exception occured: {0}", ex.Message.ToString()));
ProcessTaskAsync(item);
}
}
这用于将列表返回为按 10 分页的列表。它位于静态类中。
public static IEnumerable<IEnumerable<T>> Paged<T>(this IEnumerable<T> enumerable, int chunkSize = 10)
{
int itemsReturned = 0;
var list = enumerable.ToList();
while (itemsReturned < list.Count)
{
int currentChunkSize = Math.Min(chunkSize, list.Count - itemsReturned);
yield return list.GetRange(itemsReturned, currentChunkSize);
itemsReturned += currentChunkSize;
}
}
【问题讨论】:
标签: c# parallel-processing task-parallel-library async-await