C# 在C中同步共享资源的集合#

C# 在C中同步共享资源的集合#,c#,multithreading,C#,Multithreading,在我的C#应用程序中,我有一个静态的共享资源集合(文本处理器类),用于响应关键字。每个处理器都是有状态的,因此不能在多线程上下文中工作。我正在寻找一种很好的方法来组织它们,这样我就可以对它们进行线程安全访问 例如,我可以在每个处理器中嵌入一个同步对象 public abstract class TextProcessor { protected internal readonly object sync = new object(); public abstract void

在我的C#应用程序中,我有一个静态的共享资源集合(文本处理器类),用于响应关键字。每个处理器都是有状态的,因此不能在多线程上下文中工作。我正在寻找一种很好的方法来组织它们,这样我就可以对它们进行线程安全访问

例如,我可以在每个处理器中嵌入一个同步对象

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是的,它是一个中等规模的处理器层次结构的基类。