获取 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);
    }
}