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