C# 在C中同步共享资源的集合#
在我的C#应用程序中,我有一个静态的共享资源集合(文本处理器类),用于响应关键字。每个处理器都是有状态的,因此不能在多线程上下文中工作。我正在寻找一种很好的方法来组织它们,这样我就可以对它们进行线程安全访问 例如,我可以在每个处理器中嵌入一个同步对象C# 在C中同步共享资源的集合#,c#,multithreading,C#,Multithreading,在我的C#应用程序中,我有一个静态的共享资源集合(文本处理器类),用于响应关键字。每个处理器都是有状态的,因此不能在多线程上下文中工作。我正在寻找一种很好的方法来组织它们,这样我就可以对它们进行线程安全访问 例如,我可以在每个处理器中嵌入一个同步对象 public abstract class TextProcessor { protected internal readonly object sync = new object(); public abstract void
public abstract class TextProcessor
{
protected internal readonly object sync = new object();
public abstract void Run( string text );
}
public class DocumentProcessor
{
private static Dictionary<string,TextProcessor> s_procMap = ...;
public void Run( string [] words1, string[] words2 )
{
ThreadPool.QueueUserWorkItem( Process, words1 );
ThreadPool.QueueUserWorkItem( Process, words2 );
}
private void Process( object arg )
{
foreach( var word in words )
{
var proc = s_processor[word];
lock( proc.sync )
{
proc.Run( word );
}
}
}
公共抽象类TextProcessor
{
受保护的内部只读对象同步=新对象();
公共摘要无效运行(字符串文本);
}
公共类文档处理器
{
私有静态字典s_procMap=。。。;
公共无效运行(字符串[]字1,字符串[]字2)
{
QueueUserWorkItem(进程,字1);
QueueUserWorkItem(进程,字2);
}
私有无效进程(对象arg)
{
foreach(单词中的var单词)
{
var proc=s_处理器[字];
锁(proc.sync)
{
进程运行(word);
}
}
}
假设我不能将我的处理器重写为无状态(这是一个选项,但由于重构量太大,这是最后的选择),是否有更好的方法来表达这一点?当前方法的问题是,单个繁忙的
TextProcessor
可以停止对剩余单词的处理。如果您改为给每个TextProcessor
a(线程安全)单词队列然后您可以在不阻塞的情况下将工作排队,并让TextProcessor
将单词排出来并按顺序处理
查看的ActionBlock
。它处理排队、开始处理任务
以及在没有剩余工作的情况下最终关闭该任务
请注意,当没有工作排队时,没有线程被阻塞。这是一个重要的可伸缩性属性。如果您真的不想更改处理器…那么我将制作一个包装器
public class ProcWrapper
{
private TextProcessor _proc;
private ActionBlock<string> _actBlock;
public ProcWrapper(TextProcessor proc)
{
_proc = proc;
_actBlock = new ActionBlock<string[]>(word=>
{
_proc.Run(word);
});
}
public void AddWord(string words)
{
_actBlock.Post(word);
}
public void WaitForCompletion()
{
_actBlock.Completion.Wait();
}
}
公共类ProcWrapper
{
专用文本处理器_proc;
私有ActionBlock _actBlock;
公共ProcWrapper(textprocessorproc)
{
_proc=proc;
_actBlock=新动作块(word=>
{
_进程运行(word);
});
}
公共void AddWord(字符串字)
{
_actBlock.Post(word);
}
公共作废等待完成()
{
_actBlock.Completion.Wait();
}
}
并像以前一样使用:
Dictionary<string,ProcWrapper> s_procMap = ...;
void Run( string [] words )
{
// NOTE: This assumes the same thread will access s_procMap.
foreach(var word in words)
s_procMap[word].AddWord(word);
}
字典s_procMap=。。。;
无效运行(字符串[]个字)
{
//注意:这假设相同的线程将访问s_procMap。
foreach(单词中的var单词)
s_procMap[word].AddWord(word);
}
我想这很接近你想要的
查看有关
TPL的DataFlow
的更多信息,以及ActionBlock
的特定信息TextProcessor
是所有处理器的超级类吗?不确定为什么需要多线程?似乎所有的同步问题都可能会扼杀所有的性能优势,并显著影响性能考虑到代码的复杂性。@SergeyRybalkin文本处理导致启动时间长于预期,因此我热衷于研究各种方案来缓解这种情况。分析表明,我的输入解析是一个瓶颈,因此我在这里尝试简化它。@AhmedKRAIEM是的,它是一个中等规模的处理器层次结构的基类。