VC++ CLR获取对象的句柄(指针)

.CLR对象是没法直接存储到数组中,我在实际使用中,需要将对象存储到FIFO中,以供异步线程访问,虽然可以使用队列,但是效率比较低,而且内存占用不可控,一直都是用C++写的环形FIFO作为异步通信,目前的使用场景是,1个线程从mongodb读取数据,分配到10个异步线程去存储,之前做法是将读取到的BsonDocument进行序列化,转换为bson字符串,写入到FIFO中,但是这样做需要使用很大的FIFO,因为BSON字符串可能很大,而且会涉及到多次拷贝,最终发现可以将BsonDocument对象转换为句柄,将句柄(32位整形数)写入到FIFO,这样效率提高不少,毕竟每次只有4个字节,在异步线程中将句柄还原为对象。

System::Runtime::InteropServices::GCHandle gch;

gch = System::Runtime::InteropServices::GCHandle::Alloc(mBsonDocument);                                                                                    
mBsonDocument_Addr = (int)System::Runtime::InteropServices::GCHandle::ToIntPtr(gch);

这个mBsonDocument_Addr就是句柄,也就是个u32整形数,可以进行传输了,而不需要传输那个大的对象了,但是需要注意的是System::Runtime::InteropServices::GCHandle::Alloc实际上是将对象重新拷贝了一份,并且分配了内存,用完后需要自己手动释放内存的(我之前就是没有释放,导致大量内存泄漏)。

句柄还原为对象

gch = System::Runtime::InteropServices::GCHandle::FromIntPtr((System::IntPtr)mBsonDocument_Addr);                    
 mBsonDocument = (MongoDB::Bson::BsonDocument ^)gch.Target;

用完后记得释放内存,调用

if (gch.IsAllocated == true)    //已结分配了句柄
                        {
                            gch.Free();                    //释放掉内存
                        }    

这里吐槽一下mongodb的查询,必须限制数量,否则有100W条数据他也一次读取到内存,电脑扛不住。

query->Clear();
						query->Add("MARK", (int)0);															//查询MARK==0的数据
		
						mBsonDocument1 = nullptr;
						mBsonDocument1 = mCollection->Find(query);	//读取一条数据,不是所有的,只读取1000条
						if (mBsonDocument1 != nullptr)
						{
							if (mIEnumerator != nullptr) //2019-11-19 增加释放内存
							{
								//mIEnumerator->Dispose();
								mIEnumerator = nullptr;
							}
							mBsonDocument1->Limit=(1000);    //限制读取的数量
							mIEnumerator = mBsonDocument1->GetEnumerator();
}
发布了143 篇原创文章 · 获赞 370 · 访问量 81万+

猜你喜欢

转载自blog.csdn.net/cp1300/article/details/103186232