巧用ThreadPool.QueueUserWorkItem实现接口二次调用
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了巧用ThreadPool.QueueUserWorkItem实现接口二次调用相关的知识,希望对你有一定的参考价值。
背景
最近做了个项目有个接口涉及到批量计算的问题,耗时比较长。大家都知道,接口等待时间太长肯定是不可取的。那么只能做异步处理了;但是问题来了这个项目没有什么消息队列、redis之类的使用,本着怎么简单怎么来的思路,新搞个消息队列不现实;这时候,多线程派上用场。
再次遇到问题
于是噼里啪啦写了一顿,发现有个问题,我的方法涉及到很多ef core 数据库操作,在多线程的条件下,
报错如下:System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913
生命周期为Scope方式,随着请求的结束,实例生命周期也会被释放,因此在多线程下若共享实例,容易出现实例已释放的错误,报错如下:Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it (or one of its parent scopes) has already been disposed.Autofac at Autofac.Core.Lifetime.LifetimeScope.BeginLifetimeScope(Object tag)。通过注入IServiceProvider,
就是这种方式也是不行的,还是需要改到原来的代码,还是违背初衷。
峰回路转
本来一筹莫展的,突然想到既然接口一次太慢了,那就分2次执行,第二次可以使用多线程触发,自己调用自己的耗时接口,这样就不需要改到原来的底层逻辑,要做的仅仅是把自己的方法拆分成2个。
1、请求一个异步方法,然后接口直接返回
/// <summary>
/// 批量 添加 一级指标 数据(74.22分,全省第10名)
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
[HttpPost]
[Route("adminaddAreadatabatch")]
public bool addAreadatabatch(List<AreadataDto> entity)
// foreach (var item in entity ?? new List<AreadataDto>())
//
// try
//
_chartBll.Addbat(entity);
//
// catch (Exception ex)
//
// _logger.Error(ex);
//
//
`
ThreadPool.QueueUserWorkItem(new WaitCallback(InsertNewsInfoExt), JsonConvert.SerializeObject(entity));`
return true;
2、这里做一个http
请求
private void InsertNewsInfoExt(object info)
var client = new RestClient("http://xxxx/api/ningdeChart/updateAreadata");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
var body = info.ToString();
request.AddParameter("application/json", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
3、在原来的接口adminaddAreadatabatch
做下二次拆分,提供一个新的api
[HttpPost]
[Route("updateAreadata")]
public bool updateAreadata(List<AreadataDto> entity)
foreach (var item in entity ?? new List<AreadataDto>())
try
_logger.Info("updateAreadata");
_chartBll.updateAreadata(item.areaid, item.t1);
catch (Exception ex)
_logger.Error(ex);
return true;
问题得到解决。
以上是关于巧用ThreadPool.QueueUserWorkItem实现接口二次调用的主要内容,如果未能解决你的问题,请参考以下文章