.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 等知识了。 

如不喜,请拍!

目录
相关文章
|
4月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
312 0
|
2月前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
55 5
|
4月前
|
存储 开发框架 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`,优化了内存使用和序列化速度。
116 0
|
2月前
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
59 1
|
3月前
|
安全
List并发线程安全问题
【10月更文挑战第21天】`List` 并发线程安全问题是多线程编程中一个非常重要的问题,需要我们认真对待和处理。只有通过不断地学习和实践,我们才能更好地掌握多线程编程的技巧和方法,提高程序的性能和稳定性。
261 59
|
3月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
59 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
2月前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
42 3
|
3月前
|
安全 Java
线程安全的艺术:确保并发程序的正确性
在多线程环境中,确保线程安全是编程中的一个核心挑战。线程安全问题可能导致数据不一致、程序崩溃甚至安全漏洞。本文将分享如何确保线程安全,探讨不同的技术策略和最佳实践。
62 6
|
3月前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
87 7
|
3月前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####