我已將一個(gè)結(jié)構(gòu)數(shù)組從 C#(托管代碼)傳遞到 C(非托管代碼)。結(jié)構(gòu)的內(nèi)存在 C# 端分配。該數(shù)組以 C 代碼填充。我的代碼是多線程的。數(shù)組的填充由一個(gè)線程完成,另一個(gè)線程從結(jié)構(gòu)數(shù)組中讀取已填充的項(xiàng)。但是我無(wú)法從第二個(gè)線程讀取數(shù)據(jù),直到第一個(gè)線程退出,但是內(nèi)存由兩個(gè)線程共享。示例代碼C# 結(jié)構(gòu)public struct Data{ public IntPtr str; [MarshalAs(UnmanagedType.I4)] public int id;}在 C# 端分配結(jié)構(gòu)數(shù)組的內(nèi)存GCHandle[] handles = new GCHandle[10];for (int i = 0; i < 10; i++){ _data[i] = new Data(); byte[] bd = new byte[100]; handles[i] = GCHandle.Alloc(bd, GCHandleType.Pinned); data[i].str = handles[i].AddrOfPinnedObject();}第一個(gè)線程將此結(jié)構(gòu)數(shù)組_data傳遞給非托管代碼(C 代碼)以使用 func 進(jìn)行填充void func([In,Out] Data[] _data);第二個(gè)線程開(kāi)始讀取填充的結(jié)構(gòu)數(shù)據(jù),但第一個(gè)線程仍在填充靜態(tài)索引的數(shù)據(jù)。在這種情況下,數(shù)據(jù)可用于但顯示0,但在C端它顯示正確的填充值,即5。請(qǐng)幫助為什么結(jié)構(gòu)成員int id的數(shù)據(jù)為0。正確的值僅在第一個(gè)線程結(jié)束后出現(xiàn)。但是,由于內(nèi)存是共享的,因此,一旦被非托管代碼填充,它必須立即可用。_data[0].str_data[0].id任何幫助將不勝感激。我希望即使線程 1 沒(méi)有結(jié)束,線程 2 也必須能夠獲取已在非托管代碼中填充的索引值。
1 回答

神不在的星期二
TA貢獻(xiàn)1963條經(jīng)驗(yàn) 獲得超6個(gè)贊
由于將托管數(shù)組傳遞給非托管代碼,因此 clr 會(huì)先將該數(shù)組復(fù)制到另一個(gè)內(nèi)存塊中,然后將其傳遞給非托管函數(shù)。非托管函數(shù)完成后,clr 會(huì)將內(nèi)存封送回托管數(shù)組,然后得到結(jié)果。
解決方案是將數(shù)組地址直接與不安全代碼一起使用。
extern void func(Data* data);
fixed(Data* p = _data)
{
func(p);
}
如果您不喜歡不安全的代碼,由于結(jié)構(gòu)數(shù)組的內(nèi)存是順序的,因此您可以傳遞第一個(gè)元素的引用。但我不確定這是否足夠安全。
extern void func(ref Data data);
func(ref _data[0]);
- 1 回答
- 0 關(guān)注
- 155 瀏覽
添加回答
舉報(bào)
0/150
提交
取消