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

简介: 抱歉,其实内容并不如题!!!真正的题目应该为《.net core 并发下由于注入模式引起的线程安全问题》 背景(写测试demo所出现的异常,供大家学习与拍砖): .net core webapi项目,做了一个授权的filter(真正的生产项目的话,JWT很棒),单个接口测试没有问题,当用前端在同一.

抱歉,其实内容并不如题!!!真正的题目应该为《.net core 并发下由于注入模式引起的线程安全问题》

背景(写测试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 和 stackoverflow 的,大部分的问题都可以找到):

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

 

(2)异常 2

 

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

1、是否应该使用 Scoped 和 Transient 的,你却使用了 Singleton;

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

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

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

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

 

改为

 

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

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

这还不明显?!!!

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

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

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

如不喜,请拍!

目录
相关文章
|
19天前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
99 0
|
27天前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
4天前
|
安全
List并发线程安全问题
【10月更文挑战第21天】`List` 并发线程安全问题是多线程编程中一个非常重要的问题,需要我们认真对待和处理。只有通过不断地学习和实践,我们才能更好地掌握多线程编程的技巧和方法,提高程序的性能和稳定性。
|
17天前
|
Java
【编程进阶知识】揭秘Java多线程:并发与顺序编程的奥秘
本文介绍了Java多线程编程的基础,通过对比顺序执行和并发执行的方式,展示了如何使用`run`方法和`start`方法来控制线程的执行模式。文章通过具体示例详细解析了两者的异同及应用场景,帮助读者更好地理解和运用多线程技术。
22 1
|
2月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
2月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
77 3
|
17天前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
2月前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
2月前
|
网络协议 C语言
C语言 网络编程(十四)并发的TCP服务端-以线程完成功能
这段代码实现了一个基于TCP协议的多线程服务器和客户端程序,服务器端通过为每个客户端创建独立的线程来处理并发请求,解决了粘包问题并支持不定长数据传输。服务器监听在IP地址`172.17.140.183`的`8080`端口上,接收客户端发来的数据,并将接收到的消息添加“-回传”后返回给客户端。客户端则可以循环输入并发送数据,同时接收服务器回传的信息。当输入“exit”时,客户端会结束与服务器的通信并关闭连接。
|
2月前
|
数据采集 消息中间件 并行计算
进程、线程与协程:并发执行的三种重要概念与应用
进程、线程与协程:并发执行的三种重要概念与应用
51 0