gpt4 book ai didi

c# - 并行处理的依赖注入(inject)

转载 作者:太空狗 更新时间:2023-10-29 23:22:43 24 4
gpt4 key购买 nike

我正在尝试练习手动依赖注入(inject)(还没有框架)以消除代码中的紧耦合。这只是为了练习 - 我没有考虑具体的实现方式。

到目前为止,简单的构造函数注入(inject)工作正常。

但是,当一个类必须在并行循环中使用另一个类时,我不知道如何解决创建紧耦合的问题。示例:

public class Processor
{
private IWorker worker;
public Processor(IWorker worker)
{
this.worker = worker;
}
public List<string> DoStuff()
{
var list = new List<string>();
for (int i = 0; i < 10; i++)
{
list.Add(worker.GetString());
}
return list;
}

public List<string> DoStuffInParallel()
{
var list = new System.Collections.Concurrent.ConcurrentBag<string>();

Parallel.For(0, 10, i =>
{
//is there any trivial way to avoid this??
list.Add(new Worker().GetString());
});
return list.ToList();
}
}

public class Worker : IWorker
{
public string GetString()
{
//pretend this relies on some instance variable, so it not threadsafe
return "a string";
}
}

避免在上述情况下并行循环比标准循环慢这一明显事实,我如何编写 Processor.DoStuffInParallel() 方法来避免当前对 Worker 类?

最佳答案

解耦的一种方法是注入(inject)工厂,例如:

public List<string> DoStuffInParallel(IWorkerFactory factory)
{
var list = new System.Collections.Concurrent.ConcurrentBag<string>();

Parallel.For(0, 10, i =>
{
list.Add(factory.Create().GetString());
});
return list.ToList();
}

工厂可以是容器拥有的单例,Create()需要线程安全。

<德尔>当然请注意,您的任务不能同时改变列表 - 您需要在将工作结果添加到列表时同步访问(apols,错过了您的 ConcurrentBag )-为了减少对 bag 的争用,您可能还想查看 Parallel.For 之一用 localinit / localFinally 重载在同步到 localFinally 中的聚合/整体包之前,将结果本地聚合到每个任务列表中.

编辑
回复:我需要为 ConcurrentBag<String> 注入(inject)一个工厂吗? ?IMO,这很好创建 ConcurrentBag直接 - 它是特定于实现的细节,而不是依赖项。例如单线程实现可能将其实现为:

return Enumerable.Range(0, 10)
.Select(i => factory.Create().GetString())
.ToList();

即没有任何中间容器的显式构造。

您可以选择将方法的接口(interface)软化到public IList<string> DoStuffInParallel甚至到IEnumerable<string> (最小可能的契约(Contract)/ promise )。这里的依赖关系是 Worker ,这是您希望能够在单元测试中模拟的内容。

关于c# - 并行处理的依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24328696/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com