abpvnext Method arguments are not valid! See ValidationErrors for details
有道翻译:abpvnext方法参数无效! 有关详细信息,请参阅ValidationErrors
ABP的一个校验异常。请对比传入的实体中是否有字段是必填的,比如我的就发现 input实体里面有很多字段是加了类似这样的属性 [Required(ErrorMessage = "IsOnLine不能为空")],那么带有这些属性的字段都得在传入前赋值。
ABP的两个特性EnableValidation和DisableValidation 用来控制validation。如果想要抛弃验证特性,我们在Add方法上面添加两个特性[HttpPost]与[DisableValidation]
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.
有道翻译:无法解析实例,也无法从这个LifetimeScope创建嵌套的生命周期,因为它(或它的一个父作用域)已经被处置。

我这个消息队列的订阅事件,在取到消息之后新开一个线程去做解析和数据插入,也就是在数据插入的Repository层方法中GetDbSetAsync()执行时报上面的错误,然后
网上搜到的唯一合适的参考链接:https://www.cnblogs.com/zxsn2014/p/16478922.html
里面有这么一个描述:
生命周期为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
解决方法:
从当前应用中获取实例,构造函数注入IHost,通过host获取IServiceProvider:

在线程中通过_sp创建新的生命周期:
using (var sp = _sp.CreateScope())
{
await Task.Delay(5000);
var applyReposity = sp.ServiceProvider.GetRequiredService<IApplyReposity>();
Console.WriteLine($"taskCode:{applyReposity.GetHashCode()},taskThreaId:{Thread.CurrentThread.ManagedThreadId}");
var model = await applyReposity.GetAsync(c => 1 == 1);
sp.Dispose();
}


观察curThreaId与taskThreaId,Task.Run开启了新的线程,与当前主线程线程ID不同,当前请求中注入的IApplyReposity的实例_applyReposity编码是57588670,新线程中开启的新生命周期sp.ServiceProvider中获取的实例编码是2837748;主线程与子线程实例不再相关,解决主线程已释放,子线程获取不到实例的问题。
(1)IHOST传递到下层再获取仓储接口实例的解决办法
他的解决方法,这个解决方法是直接通过控制器调用Repository,但是我abp是中间还有service接口和类,还有domain代理类Manager,然后才能到Repository层。
所以我参照这个实例的解决办法如下:
把Ihost从hander构造方法注入,然后传递到application的构造方法注入,再传递到mannager类的构造方法。
最后再manager构造方法里通过如下代码行
_tahmCJWdTmpRepository = host.Services.GetRequiredService<ITahmCJ_wd_tmpRepository>();
取得 Repository 接口实例。
这时候再用Repository实例去操作数据就没问题了。
补充:消息处理程序hander类,HandleEventAsync方法中,还是不能再单独开线程new Thread去调用业务方法,只能在HandleEventAsync中直接调用业务处理方法。否则还是会出现生命周期异常问题。
TahmEventHandler

TahmCJ_wd_tmpAppService

TahmCJ_wd_tmpManager

(2)实际上经过后期测试发现,更改我的EventHandler 事件类继承的注入生命周期的依赖为单例模式就不会报错了。我本来用的是ITransientDependency ,修改为 ISingletonDependency即可。
不过这种方式对于一个消费消息的事件来说我觉得是不妥的。

(3)2023-4-3更新解决方案, 我之所以造出了LifetimeScope生命周期问题,是因为我在cap订阅事件中新开了线程来试图加快消息消费过程。 但是经过大佬指点,cap本身是可以设置多线程数量的,所以我完全可以取消新开线程的代码,直接在cap配置方法里增加线程数量的配置来解决快速消费消息的并发问题。
