繁体   English   中英

获取Parallel.Foreach发起方的线程ID

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM