Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 每个请求的Asp.Net核心异步延迟初始化_Multithreading_Asp.net Core_Dependency Injection_Thread Safety_Lazy Initialization - Fatal编程技术网

Multithreading 每个请求的Asp.Net核心异步延迟初始化

Multithreading 每个请求的Asp.Net核心异步延迟初始化,multithreading,asp.net-core,dependency-injection,thread-safety,lazy-initialization,Multithreading,Asp.net Core,Dependency Injection,Thread Safety,Lazy Initialization,对于我们的多租户Asp.Net Core 2.2 web应用程序中的许多端点,我们需要根据每个请求(使用异步数据库调用)从数据库中获取一些租户信息,然后根据需要重用请求管道中各个点的信息,而无需每次进行数据库调用。也就是说,我们希望在每个请求的基础上使用类似于惰性异步属性的东西 根据我读过的各种文档,范围服务的实例一次只能由一个线程(处理请求的线程)访问。因此,我相信这意味着我应该能够安全地执行以下操作: // Registered as scoped in the DI container p

对于我们的多租户Asp.Net Core 2.2 web应用程序中的许多端点,我们需要根据每个请求(使用异步数据库调用)从数据库中获取一些租户信息,然后根据需要重用请求管道中各个点的信息,而无需每次进行数据库调用。也就是说,我们希望在每个请求的基础上使用类似于惰性异步属性的东西

根据我读过的各种文档,范围服务的实例一次只能由一个线程(处理请求的线程)访问。因此,我相信这意味着我应该能够安全地执行以下操作:

// Registered as scoped in the DI container
public class TenantInfoRetriever : ITenantInfoRetriever
{
    private TenantInfo _tenantInfo;
    private bool _initialized;

    public async Task<TenantInfo> GetAsync()
    {
        // This code is obviously not thread safe, which is why it's important that no two threads are running here at the same time.
        if (!_initialized)
        {
            _tenantInfo = await GetTenantInfoAsync(); // this might actually legitimately return null, hence the need for the separate property "_initialized"
            _initialized = true;
        }
        return _tenantInfo;
    }

    private async Task<TenantInfo> GetTenantInfoAsync()
    {
        return await DoDatabaseCallToGetTenantInfo(); // of course this would use an injected EfContext instance (scoped service)
    }
}
//在DI容器中注册为作用域
公共类租户ForeTriever:ITenantInformationRetriever
{
私人租户信息(u TenantInfo);;
已初始化私有布尔;
公共异步任务GetAsync()
{
//这段代码显然不是线程安全的,这就是为什么不能有两个线程同时运行的原因。
如果(!\u已初始化)
{
_tenantInfo=await GetTenantInfoAsync();//这实际上可能会合法地返回null,因此需要单独的属性“\u initialized”
_初始化=真;
}
返回租户信息;
}
私有异步任务GetTenantInfoAsync()
{
return await DoDatabaseCallToGetTenantInfo();//当然这将使用注入的EfContext实例(作用域服务)
}
}
据我所知,这应该是可行的,因为作用域服务不需要是线程安全的

我的问题:我的假设是否正确,或者我是否遗漏了一些重要的东西

根据我读过的各种文档,作用域服务的实例一次只能由一个线程(处理请求的线程)访问

这不完全正确。当您等待操作时,线程将返回到线程池,当异步操作恢复时,将从线程池中提取一个空闲线程。 它不需要与启动它的线程完全相同

但是是的,当它的作用域被限定时,不会有两个线程同时访问它,也就是说,从ASP.NET核心端

当然,您也需要对自己的代码采取预防措施。 如果您启动两个任务/线程并同时运行它们,那么仍有可能同时访问它们

如果担心被访问,请执行双重检查锁定模式(使用volatile字段)或锁定互斥体(不是您修改的值的对象)或使用
AsyncLazy
,即从

示例(摘自)

例1:

string name;

public string Name
{
    get
    {
        lock (mutex)    // GOOD: Thread-safe
        {
            if (name == null)
                name = LoadNameFromDatabase();
            return name;
        }
    }
}
例2:

volatile string name;    // GOOD: Thread-safe

public string Name
{
    get
    {
        if (name == null)
        {
            lock (mutex)
            {
                if (name == null)
                    name = LoadNameFromDatabase();
            }
        }
        return name;
    }
}

根据我读过的各种文档,作用域服务的实例一次只能由一个线程(处理请求的线程)访问。不完全正确,因为当您等待操作时,线程将返回到线程池,当它恢复时,将从线程池中提取一个空闲线程。它不需要与启动它的线程完全相同。但是是的,不会有两个线程同时访问它。但是你有什么问题?如果您担心它会被访问,请使用双锁模式或者使用
AsyncLazy
(请参阅)。(删除了上一个链接,因为它引用的是visualstudio ts库,不应在Visual Studio扩展包Hanks@Tseng之外使用。我想我更喜欢保持简单,即不必担心锁定。根据您所说的,没有两个线程会同时访问此服务的实例,因此,这对我来说意味着锁定是不必要的。类似地,AsyncLazy方法似乎是为多线程场景设计的,所以我认为这有点过分。我的问题主要是为了确保在继续我的简单方法之前,我没有忽略一些关键的东西。如果您有兴趣将您的评论映射到回答:我很乐意将其标记为已接受。