C# . NET线程正在中止异常
我有一个ASP.NET MVC API调用,它启动了在后台运行C# . NET线程正在中止异常,c#,.net,asp.net-web-api,C#,.net,Asp.net Web Api,我有一个ASP.NET MVC API调用,它启动了在后台运行Parallel.forEach的任务。forEach运行10个并发任务,为我们传递给它的数据列表做它需要做的事情 至于API调用,我们只需将Ok(result)返回到前端,因为我只希望此任务在后台运行。完成后会通知我的 我想既然任务之间不相互依赖,我可以通过一次启动10个任务来加快这个过程,当该批任务完成后,再启动下10个任务,以此类推 DoLongRunningProcess()中的进程可能需要5秒到7分钟 这是我的问题。在DoL
Parallel.forEach
的任务。forEach运行10个并发任务,为我们传递给它的数据列表做它需要做的事情
至于API调用,我们只需将Ok(result)
返回到前端,因为我只希望此任务在后台运行。完成后会通知我的
我想既然任务之间不相互依赖,我可以通过一次启动10个任务来加快这个过程,当该批任务完成后,再启动下10个任务,以此类推
DoLongRunningProcess()
中的进程可能需要5秒到7分钟
这是我的问题。在DoLongRunningProcess()
方法的某个地方,我们得到了一个异常“Thread was being aborted”,它似乎突破了parallel.ForEach
,并在RunMyParallelLoop()
方法中被捕获到异常
更大的问题是,当我们有150多条记录要处理时,它会随机发生。有时该任务将顺利运行,有时具有相同数据的同一任务将在Parallel.ForEach
的10个批中的一个批中引发“Thread was being aborted”异常
现在,这可能是一个糟糕的/不干净的方法,所以这就是为什么我期待社区的帮助
我错过了什么
下面的代码示例
public IHttpActionResult MyMvcApiCall()
{
MyService ms = new MyService()
ms.CreateTaskAndStartprocess(someData)
result = new {message: "Your process has started"};
return Ok(result)
}
//MyService.cs
public CreateTaskAndStartprocess(SomeData someData)
{
Task.Run(() => {
RunMyParallelLoop(someData);
});
}
private RunMyParallelLoop (SomeData someData)
{
try
{
var options = new ParallelOptions {MaxDegreeOfParallelism = 10};
var exceptions = new ConcurrentQueue<Exception>();
Parallel.ForEach( someData, options, dataItem =>
{
try
{
DoLongRunningProcess(dataItem);
}
catch (Exception e)
{
//used to track any issues within DoLongRunningProcess
exceptions.Enqueue(e);
}
}
}
catch (Exception e)
{
//ThreadAbortException in DoLongRunningProcess seems to break out of Parallel.ForEach up to hear
// Other Exceptions in DoLongRunningProcess do not bubble up to here
LogError(e);
throw
}
}
private DoLongRunningProcess(dataItem)
{
try
{
updateStatusOfDataItemInDb("in porogress");
createByteArrayToCreateFile()
DoSomeIO()
updateStatusOfDataItemInDb("done");
}
catch (Exception e)
{
updateStatusOfDataItemInDb("failed");
throw;
}
}
public IHttpActionResult MyMvcApiCall()
{
MyService ms=newmyservice()
ms.CreateTaskAndStartprocess(someData)
结果=新建{消息:“您的进程已启动”};
返回Ok(结果)
}
//MyService.cs
公共CreateTask和StartProcess(SomeData SomeData)
{
Task.Run(()=>{
运行MyParallelLoop(someData);
});
}
私有RunMyParallelLoop(SomeData SomeData)
{
尝试
{
var options=new ParallelOptions{maxdegreeofpparallelism=10};
var exceptions=新的ConcurrentQueue();
Parallel.ForEach(someData,options,dataItem=>
{
尝试
{
多龙运行过程(数据项);
}
捕获(例外e)
{
//用于跟踪DoLongRunningProcess中的任何问题
例外情况。排队(e);
}
}
}
捕获(例外e)
{
//DoLongRunningProcess中的ThreadAbortException似乎打破了并行。ForEach up to hear
//DoLongRunningProcess中的其他异常不会出现在这里
对数误差(e);
扔
}
}
私有DoLongRunningProcess(数据项)
{
尝试
{
更新StatusOfDataItemIndb(“在porogress中”);
createByteArrayToCreateFile()
多索米奥()
updateStatusOfDataItemInDb(“完成”);
}
捕获(例外e)
{
updateStatusOfDataItemInDb(“失败”);
投掷;
}
}
你不能(安全地)从像ASP.NET那样的请求开始后台任务。你应该看看IHostedService
,它确实可以让你(稍微)安全地完成任务,然后从托管服务的请求和进程中添加某种生产者-消费者队列。我说“稍微”安全,因为这毕竟是一个可以随时终止的web应用程序。