[英]Get Thread ID of the initiator of a Parallel.Foreach
我有一排命令。 一个线程正在尝试执行那些命令。
其他线程可以要求暂停执行(它们将被阻塞直到当前命令执行完成),然后继续执行。
当线程想要(以固定间隔)执行那些命令时,它会标记它想要执行命令(并被阻塞,直到所有“暂停”都被删除。
唯一的问题是这些命令中的某些命令可能会尝试暂停命令执行(因为某些事件监听了其他事件,...)。
到目前为止,已处理的方法是存储执行命令的线程的ThreadId,如果暂停请求来自此线程,则忽略该请求。 (我知道,您不必告诉我这是一种肮脏的设计,但我必须这样做:()。
一类包含所有以下CommandQueue
逻辑:
public void PauseDataCommandProcessing()
{
if (Thread.CurrentThread.ManagedThreadId == m_processDataCommandThreadId)
{
return;
}
lock (m_pauseLock)
{
m_pauseCounter++;
if (m_dataCommandInProgress)
{
Monitor.Wait(m_pauseLock);
}
}
}
public void ResumeDataCommandProcessing()
{
if (Thread.CurrentThread.ManagedThreadId == m_processDataCommandThreadId)
{
return;
}
lock (m_pauseLock)
{
m_pauseCounter--;
if (m_pauseCounter == 0)
{
Monitor.PulseAll(m_pauseLock);
}
}
}
//Thoses methods are called by the command executers
public void FlagCommandsExecutionInProgress()
{
m_processDataCommandThreadId = Thread.CurrentThread.ManagedThreadId;
lock (m_pauseLock)
{
while (m_pauseCounter > 0)
{
Monitor.Wait(m_pauseLock);
}
m_dataCommandInProgress = true;
}
}
public void FlagCommandsExecutionFinished()
{
lock (m_pauseLock)
{
m_dataCommandInProgress = false;
Monitor.PulseAll(m_pauseLock);
}
}
这是我基本上执行它们的方式
CommandContainer.FlagCommandsExecutionInProgress();
try{
IEnumerable<CommandInfo> commandSet =CommandContainer.RetrieveCommands();//Get the current commands list
foreach (CommandInfo command in commandSet){
command.Execute();
}
}finally{
CommandContainer.FlagCommandsExecutionFinished();
}
为了提高这些命令的执行速度,我想按“目标”将命令重新分组(每个命令都应用于特定对象),然后并行执行每组命令。
想法是像这样执行它们:
CommandContainer.FlagCommandsExecutionInProgress();
try{
IEnumerable<IGrouping<object, CommandInfo>> groupedCommandSet =CommandContainer.RetrieveCommands().GroupBy(c=>c.Target);//Get the current commands list
Parallel.ForEach(groupedCommandSet,commandSet=>{
foreach (CommandInfo command in commandSet){
command.Execute();
}
} );
}finally{
CommandContainer.FlagCommandsExecutionFinished();
}
但是不幸的是,它们将具有不同的ThreadId,并且我遇到了一些死锁,因为它们等待自己完成。
假设我无法更改暂停请求的方式,您是否看到解决我问题的方法?
我结束了这一步:我不知道是否有更好的解决方案,但似乎可行:
private HashSet<int> m_processDataCommandThreadIds = new HashSet<int>();
public void PauseDataCommandProcessing()
{
if (m_processDataCommandThreadIds.Contains(Thread.CurrentThread.ManagedThreadId))
{
return;
}
lock (m_pauseLock)
{
m_pauseCounter++;
if (m_dataCommandInProgress)
{
Monitor.Wait(m_pauseLock);
}
}
}
public void ResumeDataCommandProcessing()
{
if (m_processDataCommandThreadIds.Contains(Thread.CurrentThread.ManagedThreadId))
{
return;
}
lock (m_pauseLock)
{
m_pauseCounter--;
if (m_pauseCounter == 0)
{
Monitor.PulseAll(m_pauseLock);
}
}
}
//Thoses methods are called by the command executers
public void FlagCommandsExecutionInProgress()
{
m_processDataCommandThreadIds.Add(Thread.CurrentThread.ManagedThreadId);
lock (m_pauseLock)
{
while (m_pauseCounter > 0)
{
Monitor.Wait(m_pauseLock);
}
m_dataCommandInProgress = true;
}
}
public void FlagCommandsExecutionFinished()
{
m_processDataCommandThreadIds.Remove(Thread.CurrentThread.ManagedThreadId);
lock (m_pauseLock)
{
m_dataCommandInProgress = false;
Monitor.PulseAll(m_pauseLock);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.