关于在C#中多线程处理仿真器的建议。模式/概念

关于在C#中多线程处理仿真器的建议。模式/概念,c#,multithreading,emulation,C#,Multithreading,Emulation,我正在做一个MIPS模拟器作为学习项目。为了获得期望的性能,我希望每个处理器总是在自己的线程中休眠,当DMA传输发生时,它们开始处理 我以前使用过BackgroundWorker,刚刚开始使用async/away指令,还阅读了有关线程池的内容。“内存空间”将被共享,因此DMA状态位是“自然”锁定机制。这些线程技术似乎没有达到我想要的效果。我错过了什么 也许这个代码示例(编译,不起作用)可以解释我的想法 public class ThreadingEmulatorCode { static

我正在做一个MIPS模拟器作为学习项目。为了获得期望的性能,我希望每个处理器总是在自己的线程中休眠,当DMA传输发生时,它们开始处理

我以前使用过BackgroundWorker,刚刚开始使用async/away指令,还阅读了有关线程池的内容。“内存空间”将被共享,因此DMA状态位是“自然”锁定机制。这些线程技术似乎没有达到我想要的效果。我错过了什么

也许这个代码示例(编译,不起作用)可以解释我的想法

public class ThreadingEmulatorCode
{
    static Memory memory = new Memory();

    public ThreadingEmulatorCode()
    {
        CPU cpu = new CPU();
        memory.OnDMAZero += cpu.zero.Execute(new DMAEventArgs());
        memory.OnDMAOne += cpu.one.Execute(new DMAEventArgs());
        cpu.Run(ref memory);
    }
}

public delegate void dmazero(DMAEventArgs args);
public delegate void dmaone(DMAEventArgs args);

public class DMAEventArgs : EventArgs
{
    public byte[] Data { get; set; }
    public uint Address { get; set; }
}

public class Memory
{
    public event dmazero OnDMAZero;
    public event dmaone OnDMAOne;

    private const uint CoprocZeroDMA = 0x1FC00000;
    private const uint CoprocOneDMA = 0xBFC00000;
    private byte[] memory;

    public Memory()
    {
        this.memory = new byte[(8 * 1024 * 1024)];
    }

    public byte this[uint address]
    {
        get
        {
            return memory[address];
        }
        set
        {
            memory[address] = value;
            if (address == CoprocZeroDMA && OnDMAZero != null)
                OnDMAZero(new DMAEventArgs());
            if (address == CoprocOneDMA && OnDMAOne != null)
                OnDMAOne(new DMAEventArgs());
        }
    }
}

public class CPU
{
    public CoprocZero zero;
    public CoprocOne one;

    public void Run(ref Memory memory)
    {
         /* Start Executing Instructions */
    }

    public CPU()
    {
        zero = new CoprocZero();
        one = new CoprocOne();
    }
}

public class CoprocZero
{
    public CoprocZero(/* Start Listening Thread */) { }

    public dmazero Execute(DMAEventArgs dmaEvent)
    {
        /* Process DMA'd Data */
        throw new NotImplementedException();
    }
}

public class CoprocOne
{
    public CoprocOne(/* Start Listening Thread */) { }

    public dmaone Execute(DMAEventArgs dmaEvent)
    {
        /* Process DMA'd Data */
        throw new NotImplementedException();
    }
}

想法还是建议?谢谢。

看起来我只是需要花更多的时间在代码上。很抱歉我原本以为TryPeek上的tight while将达到最大CPU,但它在进程列表中的CPU为零。我还没有验证总体性能,但我认为这会起作用

// Code to Test
// ThreadingExampleCode stackOverflow = new ThreadingExampleCode();
// Thread.Sleep(new TimeSpan(1, 0, 0));
public class ThreadingExampleCode
{
    public static Memory memory;
    private CoprocZero zero;
    private CoprocOne one;
    private CPU cpu;
    private Thread coprocZero;
    private Thread coprocOne;
    ConcurrentQueue<uint> coprocZeroQueue = new ConcurrentQueue<uint>();
    ConcurrentQueue<uint> coprocOneQueue = new ConcurrentQueue<uint>();

    public ThreadingExampleCode()
    {
        memory = new Memory();
        memory.OnDMAZero += MemoryOnOnDmaZero;
        memory.OnDMAOne += MemoryOnOnDmaOne;

        cpu = new CPU(memory);
        zero = new CoprocZero(memory, coprocZeroQueue);
        one = new CoprocOne(memory, coprocOneQueue);
        coprocZero = new Thread(zero.RunParm);
        coprocZero.Start();

        coprocOne = new Thread(one.RunParm);
        coprocOne.Start();

        cpu.Run();
    }

    private void MemoryOnOnDmaOne(DMAEventArgs args)
    {
        coprocOneQueue.Enqueue(args.Address);
    }

    private void MemoryOnOnDmaZero(DMAEventArgs args)
    {
        coprocZeroQueue.Enqueue(args.Address);
    }
}

public delegate void dmazero(DMAEventArgs args);

public delegate void dmaone(DMAEventArgs args);

public class DMAEventArgs : EventArgs
{
    public uint Address { get; set; }
}

public class Memory
{
    public event dmazero OnDMAZero;
    public event dmaone OnDMAOne;

    public const uint CoprocZeroDMA = 1 * 1024 * 1024;
    public const uint CoprocOneDMA = 2 * 1024 * 1024;
    private byte[] memory;

    public Memory()
    {
        this.memory = new byte[(8 * 1024 * 1024)];
    }

    public byte this[uint address]
    {
        get { return memory[address]; }
        set
        {
            memory[address] = value;
            if (address == CoprocZeroDMA && OnDMAZero != null)
                OnDMAZero(new DMAEventArgs());
            if (address == CoprocOneDMA && OnDMAOne != null)
                OnDMAOne(new DMAEventArgs());
        }
    }
}

public class CPU
{
    private Memory memory;
    public CPU(Memory inMemory)
    {
        memory = inMemory;
    }

    public void Run()
    {
        /* Start Executing Instructions */
        memory[Memory.CoprocZeroDMA] = 0x01;
        memory[Memory.CoprocOneDMA] = 0x01;
    }
}

public class CoprocZero
{
    private ConcurrentQueue<uint> queueToMonitor;
    private Memory memory;
    public CoprocZero(Memory inMemory, ConcurrentQueue<uint> queue)
    {
        memory = inMemory;
        queueToMonitor = queue;
    }

    public void RunParm()
    {
        uint memoryAddress;
        while (!queueToMonitor.TryPeek(out memoryAddress)) { };

        if (queueToMonitor.TryDequeue(out memoryAddress))
        {
            Debugger.Break();
        }
    }
}

public class CoprocOne
{
    private Memory memory;
    private ConcurrentQueue<uint> queueToMonitor;
    public CoprocOne(Memory inMemory, ConcurrentQueue<uint> queue)
    {
        memory = inMemory;
        queueToMonitor = queue;
    }

    public void RunParm()
    {
        uint memoryAddress;
        while (!queueToMonitor.TryPeek(out memoryAddress)) { };

        if (queueToMonitor.TryDequeue(out memoryAddress))
        {
            Debugger.Break();
        }
    }
}
//要测试的代码
//ThreadingExampleCode stackOverflow=新的ThreadingExampleCode();
//睡眠(新的时间跨度(1,0,0));
公共类线程示例代码
{
公共静态存储器;
私有CoprocZero;
私用CoprocOne;
专用CPU;
私有线程coprocZero;
专用线程coprocOne;
ConcurrentQueue coprocZeroQueue=新ConcurrentQueue();
ConcurrentQueue coprocOneQueue=新ConcurrentQueue();
公共线程ExampleCode()
{
内存=新内存();
memory.OnDMAZero+=memoryondmazero;
memory.OnDMAOne+=memoryondmaOne;
cpu=新的cpu(内存);
zero=新的CoprocZero(内存,coprocZeroQueue);
一=新的CoprocOne(内存,coprocOneQueue);
coprocZero=新线程(zero.RunParm);
coprocZero.Start();
coprocOne=新线程(one.RunParm);
coprocOne.Start();
cpu.Run();
}
私有无效备忘录OndMaone(DMAEventArgs args)
{
coprocOneQueue.Enqueue(args.Address);
}
私人无效备忘录Ondmazero(DMAEventArgs args)
{
coprocZeroQueue.Enqueue(args.Address);
}
}
公共代表无效dmazero(DMAEventArgs args);
公共代表无效dmaone(DMAEventArgs args);
公共类DMAEventArgs:EventArgs
{
公共uint地址{get;set;}
}
公共类内存
{
公共活动dmazero OnDMAZero;
公共活动dmaone OnDMAOne;
公共常数CoprocZeroDMA=1*1024*1024;
公共建筑面积=2*1024*1024;
专用字节[]存储器;
公共内存()
{
this.memory=新字节[(8*1024*1024)];
}
公共字节此[uint地址]
{
获取{返回内存[地址];}
设置
{
存储器[地址]=值;
if(地址==CoprocZeroDMA&&OnDMAZero!=null)
OnDMAZero(新的DMAEventArgs());
if(地址==CoprocOneDMA&&OnDMAOne!=null)
OnDMAOne(新的DMAEventArgs());
}
}
}
公共类CPU
{
专用存储器;
公共CPU(内存中的内存)
{
内存=内存;
}
公开募捐
{
/*开始执行指令*/
内存[memory.CoprocZeroDMA]=0x01;
内存[memory.CoprocOneDMA]=0x01;
}
}
公共类CoprocZero
{
私有并发队列监视器;
专用存储器;
公共CoprocZero(内存中的内存,ConcurrentQueue队列)
{
内存=内存;
queueToMonitor=队列;
}
公共无效RunParm()
{
uint存储器地址;
而(!queueToMonitor.TryPeek(out memoryAddress)){};
if(queueToMonitor.TryDequeue(out memoryAddress))
{
Debugger.Break();
}
}
}
公共级CoprocOne
{
专用存储器;
私有并发队列监视器;
公共CoprocOne(内存中的内存,ConcurrentQueue队列)
{
内存=内存;
queueToMonitor=队列;
}
公共无效RunParm()
{
uint存储器地址;
而(!queueToMonitor.TryPeek(out memoryAddress)){};
if(queueToMonitor.TryDequeue(out memoryAddress))
{
Debugger.Break();
}
}
}

与实际发生的情况相比,您期望的是什么?我想我不清楚如何为睡眠线程提供新的工作负载。首先,您的示例中没有执行任何多线程。这里的所有内容都将在一个线程中运行。对于多线程,您需要查看
System.threading
名称空间。这是一个Q&D示例,试图展示我想要做的事情,我将看看是否可以对其进行一些改进。如果您担心锁定问题,在.Net中有几种不同的技术可以更好地处理它,而不是尝试处理您自己的锁定。例如,看一看具有内置线程安全访问的类的示例和。即使如此,如果您想执行自己的锁定,一种常见的方法是创建一个
private Object lockObj=new Object()和简单的
锁(lockObj){/*…*/}