gpt4 book ai didi

c# - ILGenerated 方法中的 System.ObjectDisposedException

转载 作者:太空宇宙 更新时间:2023-11-03 15:50:21 27 4
gpt4 key购买 nike

我添加到 ILGenerator 字符串

ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);

ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());

进入基本代码

private ReadItemDelegate _read;

/// <summary>
/// Init Get method of instance
/// </summary>
private void InitGetMethod()
{
var ti = typeof (int);
Type[] methodArgs2 = { _globalType, ti, ti, ti, ti, ti, ti, ti, ti, ti, ti };// 10 elements

#region this.Get = double(int, .., int) { return _shift0[i0] + .. + _shiftn[in] }
var dynamicMethod = new DynamicMethod("", ChildrenType, methodArgs2, _globalType);// create dynmic method

var ilGen = dynamicMethod.GetILGenerator();
var fiShift = new FieldInfo[_dims.Length];

for (var i = 0; i < _dims.Length; i++) // get links to all shift arrays
{
fiShift[i] = _globalType.GetField("_shift" + i, BindingFlags.NonPublic | BindingFlags.Instance);
}

var ldargs = new[] {OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3};

var readField = _globalType.GetField("_read", BindingFlags.NonPublic | BindingFlags.Instance);
if (readField == null) throw new ArgumentNullException("_read");

ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);

for (var i = 0; i < _dims.Length; i++)
{

ilGen.Emit(OpCodes.Ldarg_0); //push link to class member
ilGen.Emit(OpCodes.Ldfld, fiShift[i]); //push link to shift array
if (i < 3) // push next param
ilGen.Emit(ldargs[i]);
else
ilGen.Emit(OpCodes.Ldarg_S, i+1);

ilGen.Emit(OpCodes.Ldelem_I8); // pop 3 vars and push value from our array by param as index. Result as I8

if (i>0) ilGen.Emit(OpCodes.Add); // pop 2 vars, summ and push back

}

ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());

ilGen.Emit(OpCodes.Ret);

Get = (GetItemDelegate) dynamicMethod.CreateDelegate( typeof(GetItemDelegate), this); // save method as Get variable
#endregion
}

当我尝试使用时

this.Get(1,2,3)

我遇到了这个错误,但是当我使用

this._read(2568)

我得到了正确的结果。

代码中哪里可能存在错误?

任何试图提供帮助的人提前致谢。

这是解释错误的简短示例:

using System;
using System.Collections.Generic;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{

public class test
{

public delegate double GetItemDelegate(int i0 = 0, int i1 = 0, int i2 = 0);
public delegate double ReadItemDelegate(Int64 offset);


Type _globalType = typeof(test);
Type ChildrenType = typeof(double);

public GetItemDelegate Get;
private ReadItemDelegate _read;

public test()
{
var file = MemoryMappedFile.CreateOrOpen("file", 123);
var readMethod = typeof(MemoryMappedViewAccessor).GetMethod("ReadDouble");
var viewAccessor = file.CreateViewAccessor(0, 123);
_read = (ReadItemDelegate)Delegate.CreateDelegate(typeof(ReadItemDelegate), viewAccessor, readMethod);


var ti = typeof(int);
Type[] methodArgs2 = { _globalType, ti, ti, ti };// 10 elements

var dynamicMethod = new DynamicMethod("", ChildrenType, methodArgs2, _globalType);// create dynmic method
var ilGen = dynamicMethod.GetILGenerator();


var readField = _globalType.GetField("_read", BindingFlags.NonPublic | BindingFlags.Instance);

ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);

ilGen.Emit(OpCodes.Ldc_I4, 3214);
ilGen.Emit(OpCodes.Conv_I8);

ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());

ilGen.Emit(OpCodes.Ret);

Get = (GetItemDelegate)dynamicMethod.CreateDelegate(typeof(GetItemDelegate), this); // save method as Get variable
}
}
class Program
{

static void Main(string[] args)
{
var tmp = new test();

Console.WriteLine(tmp.Get());

Console.ReadLine();
}

}
}

最佳答案

以编辑中的示例为例:问题很简单,就是不正确的字段访问和方法调用;看这里:

ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, readField);

ilGen.Emit(OpCodes.Ldc_I4, 3214);
ilGen.Emit(OpCodes.Conv_I8);

ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());
ilGen.Emit(OpCodes.Ret);

这里,_readviewAccessor.ReadDouble 的委托(delegate) - 即 ReadDouble 是实例方法,而 viewAccessor 是目标实例。我们有两个选择:

  • 针对我们之前存储在 viewAccessor 中的实例调用 ReadDouble
  • 在委托(delegate)上调用 Invoke

我们可以通过类似的方式来完成其中的第二个:

// removed: ilGen.Emit(OpCodes.Call, _read.GetMethodInfo());
ilGen.Emit(OpCodes.Callvirt, _read.GetType().GetMethod("Invoke"));
ilGen.Emit(OpCodes.Ret);

请注意,您必须使用 3214 以外的值,或者将文件/ View 访问器的容量/大小更改为大于 123 的值。

但是,忘记 _read 并存储 viewAccessor 并调用 virt readMethod 可能会更有效。例如:

private MemoryMappedViewAccessor _acc;

// ...

var viewAccessor = file.CreateViewAccessor(0, 123 * 1000);
_acc = viewAccessor;
var accField = _globalType.GetField("_acc",
BindingFlags.NonPublic | BindingFlags.Instance);

// ...

ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldfld, accField);

ilGen.Emit(OpCodes.Ldc_I4, 3214);
ilGen.Emit(OpCodes.Conv_I8);

ilGen.Emit(OpCodes.Callvirt, readMethod);
ilGen.Emit(OpCodes.Ret);

关于c# - ILGenerated 方法中的 System.ObjectDisposedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26102000/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com