Autofac - 解决多线程环境中的依赖关系

2024-04-17

public class MultithreadTester
{

    public void Run()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<ManualWork>().As<IWork>();
        builder.RegisterType<ColabManualWork>().As<IColabWork>();
        builder.RegisterType<RelaxAfterManualWork>().As<IRelax>();

        var container = builder.Build();

        //#1 - Simple single thread
        using (var scope = container.BeginLifetimeScope())
        {
            var work = scope.Resolve<IWork>();
            work.DoWork();
        }

        //#2 - Resolving dependecies in worker threads in scopes of these threads without passing lifetime scopes are container into implementation
        using (var scope = container.BeginLifetimeScope())
        {
            var work = scope.Resolve<IColabWork>();
            work.DoWork();
        }

        //#3 - Resolving dependecies in worker threads when original scope is already gone (simulates fast request on same service which spawns threads for request processing)
        IColabWork workForSample3;
        using (var scope = container.BeginLifetimeScope())
        {
            workForSample3 = scope.Resolve<IColabWork>();
        }
        workForSample3.DoWork();

        Console.ReadKey();

    }

    public interface IRelax
    {
        void DoRelax();
    }

    public class RelaxAfterManualWork : IRelax
    {
        public void DoRelax()
        {
            Console.WriteLine("Relaxing after hard work...");
            Thread.Sleep(1000);
            Console.WriteLine("Relax is done...");
        }
    }


    public interface IWork
    {
        void DoWork();
    }

    public class ManualWork : IWork
    {
        private readonly IRelax _relaxActivity;

        public ManualWork(IRelax relaxActivity)
        {
            _relaxActivity = relaxActivity;
        }

        public void DoWork()
        {
            Console.WriteLine("Ufff, this is so hard...");
            Thread.Sleep(5000);
            Console.WriteLine("Work is done...");
            _relaxActivity.DoRelax();
        }
    }

    public interface IColabWork
    {
        void DoWork();
    }

    public class ColabManualWork : IColabWork
    {
        public void DoWork()
        {
            Console.WriteLine("We must discuss how to share the workload...");
            Thread.Sleep(1500);

            Action action = () => 
            {
                //IT WOULD BE FINE TO HAVE RESOLVED DEPENDENCIES PER THREAD AND IN THREAD OWN LIFETIMESCOPE

                Console.WriteLine("Ufff, this is so hard but working with my buddies helps...");
                Thread.Sleep(2500);
                Console.WriteLine("Work is done...");
                var relaxActivity = new RelaxAfterManualWork();
                relaxActivity.DoRelax();
            };

            var thread1 = new Thread(() => { action(); });
            var thread2 = new Thread(() => { action(); });
            thread1.Start();
            thread2.Start();

            thread1.Join();
            thread2.Join();
        }
    }


}

在标记为 #1 的示例中,我正在解析 IWork 并运行一些操作。对于单线程环境,我了解 DI 中发生了什么、应该如何使用 DI、lifetimescope 以及如何解决依赖关系。

但我很难理解多线程环境下的 DI。我尝试通过示例#2、#3 来演示我遇到的一些问题。在这些示例中,我需要以某种方式解决 LifetimeScope 中的依赖关系,该依赖关系将为 ColabManualWork 中的每个线程创建。当然,我不希望引用 Autofac 中的任何类来防止耦合。

我什至创建了一个简单的工厂,适合从当前的 LifetimeScope 创建嵌套的 LifetimeScope:

public interface IIsolatedLifetimeScopeFactory<TA>
{
    void Create(Action<TA> action);
}

public class IsolatedLifetimeScopeFactory<TA> : IIsolatedLifetimeScopeFactory<TA>
{
    private readonly ILifetimeScope _scope;

    public IsolatedLifetimeScopeFactory(ILifetimeScope scope)
    {
        _scope = scope;
    }

    public void Create(Action<TA> action)
    {
        using (var subScope = _scope.BeginLifetimeScope())
        {
            var a = subScope.Resolve<TA>();
            action(a);
        }
    }
}

但我不太喜欢这个解决方案。这里存在三个大问题 - 1)所有逻辑都必须在 lambda 函数(或等效方法)中; 2) 将来,如果再次处置父作用域,Autoflac 可以重新实现处置子作用域的功能(此功能已经存在几个月了); 3) 如示例#3 所示,我可以在 ColabManualWork 中的任何功能启动之前处置父 LifetimeScope,因此我的工厂将使用已处置的 LifetimeScope。

有人可以帮助我如何有效地解决工作线程中的问题吗?我读到了一些与 SimpleInjector 相关的内容在多线程应用程序中使用依赖注入 http://simpleinjector.readthedocs.org/en/latest/howto.html#multi-threaded-applications但我没有完全理解它,而且它与 Autofac 无关。那篇文章里写到在多线程应用程序中,每个线程都应该有自己的对象图。这意味着您通常应该在线程执行开始时调用一次 container.GetInstance() 来获取用于处理该线程的根对象

如何在不与 Autofac 耦合以及线程相关的生命周期范围内解决工作线程中的依赖关系?


要为每个线程提供自己的生命周期范围,您只需注册您的IsolatedLifetimeScopeFactory as SingleInstance。这将解决您的担忧 2) 和 3)

[TestMethod]
public void MyTestMethod()
{
    var cb = new ContainerBuilder();
    cb.RegisterGeneric(typeof(IsolatedLifetimeScopeFactory<>))
        .SingleInstance();
    var container = cb.Build();

    using (var scope1 = container.BeginLifetimeScope("scope1"))
    using (var scope2 = scope1.BeginLifetimeScope("scope2"))
    {
        var factory = scope2.Resolve<IsolatedLifetimeScopeFactory<object>>();
        var tag = factory._scope.Tag; // made _scope public for testing purposes
        Assert.AreNotEqual("scope1", tag);
        Assert.AreNotEqual("scope2", tag);

        // This particular string "root" is probably not guaranteed behavior, but
        // being in the root scope is guaranteed for SingleInstance registrations.
        Assert.AreEqual("root", tag);
    }
}

您的担忧 1) 可以通过使用不同的抽象来解决。例如,您可以将其添加到IsolatedLifetimeScopeFactory

public Autofac.Features.OwnedInstances.Owned<TA> Create()
{
    return _scope.Resolve<Autofac.Features.OwnedInstances.Owned<TA>>();
}

你可以隐藏Owned如果你真的想的话,可以在抽象背后,尽管我会说这有点矫枉过正。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Autofac - 解决多线程环境中的依赖关系 的相关文章

  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 如何进行带有偏差的浮点舍入(始终向上或向下舍入)?

    我想以偏置舍入浮动 要么总是向下 要么总是向上 代码中有一个特定的点 我需要这个 程序的其余部分应该像往常一样四舍五入到最接近的值 例如 我想四舍五入到最接近的 1 10 倍数 最接近 7 10 的浮点数约为 0 69999998807 但
  • Blazor 与 Razor

    随着 Blazor 的发明 我想知道这两种语言之间是否存在显着的效率 无论是在代码创建方面还是在代码的实际编译 执行方面 https github com SteveSanderson Blazor https github com Ste
  • 有什么工具可以说明每种方法运行需要多长时间?

    我的程序的某些部分速度很慢 我想知道是否有我可以使用的工具 例如它可以告诉我可以运行 methodA 花了 100ms 等等 或者类似的有用信息 如果您使用的是 Visual Studio Team System 性能工具 中有一个内置分析
  • Guid 应包含 32 位数字和 4 个破折号

    我有一个包含 createuserwizard 控件的网站 创建帐户后 验证电子邮件及其验证 URL 将发送到用户的电子邮件地址 但是 当我进行测试运行时 单击电子邮件中的 URL 时 会出现以下错误 Guid should contain
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • TextBox 焦点的 WinForms 事件?

    我想添加一个偶数TextBox当它有焦点时 我知道我可以用一个简单的方法来做到这一点textbox1 Focus并检查布尔值 但我不想那样做 我想这样做 this tGID Focus new System EventHandler thi
  • 为什么 BOOST_FOREACH 不完全等同于手工编码的?

    From 增强文档 http www boost org doc libs 1 48 0 doc html foreach html foreach introduction what is literal boost foreach li
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • C# 搜索目录中包含字符串的所有文件,然后返回该字符串

    使用用户在文本框中输入的内容 我想搜索目录中的哪个文件包含该文本 然后我想解析出信息 但我似乎找不到该字符串或至少返回信息 任何帮助将不胜感激 我当前的代码 private void btnSearchSerial Click object
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • 是否有一个 C++ 库可以从 PDF 文件中提取文本,例如 PDFBox for Java? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 去年 我使用 PDFBox 在 Java 中创建了一个应用程序来获取某些 PDF 文件中的原始文本 现在
  • 无法使用 Ninject 将依赖项注入到从 Angular 服务调用的 ASP.NET Web API 控制器中

    我将 Ninject 与 ASP NET MVC 4 一起使用 我正在使用存储库 并希望进行构造函数注入以将存储库传递给其中一个控制器 这是实现 StatTracker 接口的上下文对象 EntityFramework public cla
  • 为什么我使用google'smtp'无法发送电子邮件?

    我有以下程序使用 smtp gmail com 587 发送电子邮件 namespace TestMailServer class Program static void Main string args MailMessage mail
  • 我应该在应用程序退出之前运行 Dispose 吗?

    我应该在应用程序退出之前运行 Dispose 吗 例如 我创建了许多对象 其中一些对象具有事件订阅 var myObject new MyClass myObject OnEvent OnEventHandle 例如 在我的工作中 我应该使
  • 热重载时调用方法

    我正在使用 Visual Studio 2022 和 C 制作游戏 我想知道当您热重新加载应用程序 当它正在运行时 时是否可以触发一些代码 我基本上有 2 个名为 UnloadLevel 和 LoadLevel 的方法 我想在热重载时执行它
  • Swagger 为 ASP.CORE 3 中的字典生成错误的 URL

    当从查询字符串中提取的模型将字典作为其属性之一时 Swagger 会生成不正确的 URL 如何告诉 Swagger 更改 URL 中字典的格式或手动定义输入参数模式而不自动生成 尝试使用 Swashbuckle 和 NSwag 控制器 pu

随机推荐

  • CruiseControl.Net + SSL

    因此 我刚刚在我的 PC 上安装了 Cruisecontrol NET 并且使用 VisualSVN 通过 https 和 虚拟 证书进行 SVN 托管 所有这些都在我的本地电脑上 问题是 当我尝试运行 Cruisecontrol NET
  • 如何在页面加载时将页面滚动到底部?

    要求 我想在页面加载时将内容滚动到页面底部 这是我的 html 代码
  • 宏定义确定大端还是小端机?

    是否有一行宏定义来确定机器的字节顺序 我正在使用以下代码 但将其转换为宏会太长 unsigned char test endian void int test var 1 unsigned char test endian unsigned
  • 默认情况下,ASP.NET MVC 4 是否需要额外的 XSS 处理

    默认情况下 ASP NET MVC 4 会忽略帖子消息中的 HTML 输入 如果我没有明确接受 HTML 是否需要编写任何代码来保护我的网站免受 XSS 攻击 我不会使用 AllowHtml or ValidateInput false 我
  • 镜头变焦模糊变量

    我在使用时遇到困难zoom函数由下式给出Control Lens 使用我的自定义 monad 变压器HearthMonad 我不知道如何满足GHC的 模棱两可型 投诉 有问题的代码位于drawCard 我该如何解决这个问题 我是否必须创建自
  • phpmyadmin自动注销时间

    如何更改 phpmyadmin 自动注销时间 它会在 1440 秒后自动注销 这对我来说非常低 如何更改选项或完全删除登录请求 更改 php ini 将更改服务器上运行的所有网站的会话持续时间 要仅为 PhpMyAdmin 更改它 请打开c
  • 使用单独的规则定义和实例化时,Boost Spirit X3 AST 无法处理语义操作

    我尝试将 Boost Spirit X3 与语义操作结合使用 同时将结构解析为 AST 如果我使用没有单独定义和实例化的规则 它就可以正常工作 例如 include
  • Facebook 应用程序选项卡 -> 使用 PHP 进行外部链接

    我目前在 Facebook 选项卡上有一个应用程序 我想知道是否有办法让我深入链接到该应用程序选项卡上的项目 例子 用户在应用程序中 正在搜索书籍 找到一本他们喜欢的书 并想与朋友分享 他们点击分享它 我可以提取所有信息 但是我没有深层链接
  • java - JUnit 测试失败挂钩上的 Cucumber

    我们使用 Cucumber JVM 编写验收测试脚本 并使用 JUnit 来执行它们 通过 JUnit Cucumber 运行程序 由于这些测试涉及 Selenium WebDriver 因此我希望能够在测试失败时截取屏幕截图 我有代码 如
  • 如何在 Dreamweaver 中设置 PHP 测试服务器?

    我正在尝试设置一个 PHP 服务器 以便我可以使用 Dreamweaver 中的 实时 功能 此外还可以在浏览器中预览 而不必每次都通过 FTP 应用程序上传 php 文件 这效率不高当我想做快速的小预览时 我已经设置了一个新网站 并在本地
  • Javascript 字符串到 int 的转换

    我在页面中嵌入了以下 JS var round Math round var id this attr id var len id length var indexPos len 1 index of the number so that
  • 液态状态机:它是如何工作的以及如何使用它?

    我现在正在学习LSM 液态状态机 我试图了解它们到底是如何用于学习的 我对在网上读到的内容感到非常困惑 我将写出到目前为止我所理解的内容 但这可能是不正确的 所以如果您能纠正我并解释什么是正确的 我会很高兴 LSM 根本没有经过训练 它们只
  • Scala 突破地图

    当满足这样的条件时 我需要打破 seq 映射 其中foo将返回一个对象列表 其中大小取决于找到 targetId 所需的时间 def foo ids Seq String targetId String ids map id gt getO
  • Apache Ivy 如何解析 ivysettings.xml 文件中提供的工件模式中的变量?

    如果我的 ivysettings xml 文件包含
  • 使用 php 调用 __construct 内的函数

    一个简单的 PHP 问题 我找不到答案 是否可以从 construct 调用函数 例如 如果我使用 My Controller 解决方案here http davidwinter me articles 2009 02 21 authent
  • 更改 HTML5 音频标签中的控件颜色 [重复]

    这个问题在这里已经有答案了 是否可以更改 HTML5 音频标签中的 播放 暂停 和 音量 颜色 使用 Firefox 时它们的颜色非常深 使播放器看起来像是禁用的 答 不可以 目前 您无法更改 HTML5 音频标签的控件颜色 如果启用控件属
  • 一组内所有对的组合

    我想计算你可以组成一个集合的所有可能的对列表 例如 input 1 2 3 4 5 6 output 1 2 3 4 5 6 2 3 4 5 1 6 2 4 1 3 5 6 注意 这个例子只是输出中的一些随机内容 大部分都被删除了 我不关心
  • 获得正确的环面 Delaunay 三角剖分(使用 python)

    我正在尝试使用以下方法对圆环进行三角测量scipy spatial Delaunay 函数 但无法得到想要的结果 这是我的代码 from scipy spatial import Delaunay NTheta 26 NR 8 a0 1 0
  • 如何在文本框中按 Tab 键后触发事件

    我想触发一个事件 例如当我点击时显示警报消息Tab文本框中的键
  • Autofac - 解决多线程环境中的依赖关系

    public class MultithreadTester public void Run var builder new ContainerBuilder builder RegisterType