获取 Parallel.Foreach 发起者的线程 ID
Get Thread ID of the initiator of a Parallel.Foreach
我有一列命令。一个线程正在尝试执行这些命令。
其他线程可以请求暂停执行(它们将被阻塞直到当前命令执行完成),然后恢复它们。
当线程想要执行这些命令时(定期)它会标记它想要执行命令(并被阻塞直到所有 "pause" 被删除。
唯一的问题是这些命令中的一些可能会尝试暂停命令执行(因为某些事件监听其他事件,...)。
目前的处理方式是存储执行命令的线程的ThreadId,如果是来自该线程的暂停请求则忽略。
(你不必告诉我这是一个糟糕的设计,我知道,但我必须处理它:( ).
一个 class 包含所有这些 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();
}
为了提高执行这些命令的速度,我想通过"Target"重新组合命令(每个命令应用于特定对象),然后并行执行每组命令。
我的想法是像这样执行它们:
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);
}
}
我有一列命令。一个线程正在尝试执行这些命令。
其他线程可以请求暂停执行(它们将被阻塞直到当前命令执行完成),然后恢复它们。
当线程想要执行这些命令时(定期)它会标记它想要执行命令(并被阻塞直到所有 "pause" 被删除。
唯一的问题是这些命令中的一些可能会尝试暂停命令执行(因为某些事件监听其他事件,...)。
目前的处理方式是存储执行命令的线程的ThreadId,如果是来自该线程的暂停请求则忽略。 (你不必告诉我这是一个糟糕的设计,我知道,但我必须处理它:( ).
一个 class 包含所有这些 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();
}
为了提高执行这些命令的速度,我想通过"Target"重新组合命令(每个命令应用于特定对象),然后并行执行每组命令。
我的想法是像这样执行它们:
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);
}
}