欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.net core并发下线程安全问题详解

程序员文章站 2023-12-10 23:36:22
抱歉,其实内容并不如题!!! 背景(写测试demo所出现的异常,供大家学习与拍砖): .net core webapi项目,做了一个授权的filter(真正的生产项目的...

抱歉,其实内容并不如题!!!

背景(写测试demo所出现的异常,供大家学习与拍砖):

.net core webapi项目,做了一个授权的filter(真正的生产项目的话,jwt很棒),单个接口测试没有问题,当用前端在同一个页面调用多个接口的时候,运行服务,打开页面,然后……exceptions……(真正的开发中大家应该也会遇到)

异常1:an attempt was made to use the context while it is being configured. a dbcontext instance cannot be used inside onconfiguring since it is still being configured at this point. this can happen if a second operation is started on this context before a previous operation completed. any instance members are not guaranteed to be thread safe.

异常2:a second operation started on this context before a previous operation completed. any instance members are not guaranteed to be thread safe.

异常3:invalid attempt to call read when reader is closed.

异常4:unable to cast object of type 'system.data.providerbase.dbconnectionclosedconnecting' to type 'system.data.sqlclient.sqlinternalconnectiontds'.

异常5:object reference not set to an instance of an object.

异常6:不允许启动新事务,因为有其他线程正在该会话中运行。

异常7:an error occurred while updating the entries. see the inner exception for details.

尝试运行了n多遍,嗯,挺不稳定的(代码垃圾!),那看看异常吧

一看很容易理解:在前一个操作完成之前,在此上下文中启动第二个操作。任何实例成员都不能保证是线程安全的。就是说,我在用这个上下文的时候,你来抢个屁……

这个可能发生在并发的情况下,同时使用了同一个上下文……那么打开一个页面,为什么会同时使用同一个上下文呢?好吧,在这里要负荆请罪了(可以说是自己的问题)

我在filter里面有查询,用到数据库上下文<dbcontext> 。罪过咯,直接想在filter里面过滤黑名单,所以查了数据库(这个业务是不合理的,这是一个作死的行为,请谨慎看待,这里做学习讨论之用)。

public class authfilterattribute : actionfilterattribute
{

 public override void onactionexecuting(actionexecutingcontext context)
 {

  base.onactionexecuting(context);
    .....
  
  //判断是否在黑名单内
  var blacklist = _app.getblacklist();
  ......
 }}

这里为什么用 actionfilterattribute ?是因为测试的时候要监测一下接口运行的整个过程,so……

然后还有一些错是:对象引用未设置为对象的实例。这个错误太常见,不就是对象为null了吗?但是,未实例化对象在业务逻辑上的情况太多了。我的应该有:

1、没有获取到当前对象,这是.net core,不是.net,不是因为没有new对象。是注入中没有注入成功,获取注入后,没有获取到。(但我本来运行的好好的,是因为一下是打开对接的页面才发生的问题,可以排除了)

2、本来已经实例的对象被回收了……(这可能性嘛……有一定的可能,但发生在哪呢?)

找啊找,其实方向有了,但是自己却没想起来……

其实如果不确定的话,倒是可以先找找别人是怎么说的(不是为了装x,找开发上的问题我是推荐 github 和 * 的,大部分的问题都可以找到):

(1)异常 1 还有同样 一条搜索结果

.net core并发下线程安全问题详解

.net core并发下线程安全问题详解

(2)

 .net core并发下线程安全问题详解

虽然以上找的不一定是真正的答案,至少提供了一个方向,并且你至少可以尝试性地去解决一下。这里提供的方向其实很明确:

1、是否应该使用 scoped 和 transient 的,你却使用了 singleton;

2、多线程中使用了 async 却没有配对的使用 await;

至少我找到的关键点是这两个。

那怎么找到并解决这个问题呢,.net core都是注入的,当然 authfilterattribute 也是注入的。跑到 startup一看,很明显,问题出在哪里了 -- 单例!本应该是scoped模式的,却用了单例。

那就将 authfilterattribute 换一种注入模式就行啦。

.net core并发下线程安全问题详解 

改为

.net core并发下线程安全问题详解

我使用的是filter,filter有自己的生命周期,去确认一下:filter的官方文档

看到一张图!!!(当然你也可以细细研读一下这个文档)如下:

.net core并发下线程安全问题详解

这还不明显?!!!

filter会被回收的!!!这同样解释了 异常3、4、5、6、7所发生的原因。

ok,问题已经解决了,这是在开发中遇到的问题,可以说是涉及到.net core 本身的运行机制。

我算是一个应用型的程序员,喜欢在应用中学习底层的东西。那么接下来当然就可以扩展 singleton、scoped 和 transient 等知识了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。