gpt4 book ai didi

c# - 防止委托(delegate)被垃圾收集

转载 作者:太空狗 更新时间:2023-10-30 00:25:36 25 4
gpt4 key购买 nike

我目前正在尝试将 C# 委托(delegate)编码为 C++ 函数指针,我查看了 example from Microsoft :

// MarshalDelegate1.cpp
// compile with: /clr
#include <iostream>

using namespace System;
using namespace System::Runtime::InteropServices;

#pragma unmanaged

// Declare an unmanaged function type that takes two int arguments
// Note the use of __stdcall for compatibility with managed code
typedef int (__stdcall *ANSWERCB)(int, int);

int TakesCallback(ANSWERCB fp, int n, int m) {
printf_s("[unmanaged] got callback address, calling it...\n");
return fp(n, m);
}

#pragma managed

public delegate int GetTheAnswerDelegate(int, int);

int GetNumber(int n, int m) {
Console::WriteLine("[managed] callback!");
return n + m;
}

int main() {
GetTheAnswerDelegate^ fp = gcnew GetTheAnswerDelegate(GetNumber);
GCHandle gch = GCHandle::Alloc(fp);
IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp);
ANSWERCB cb = static_cast<ANSWERCB>(ip.ToPointer());
Console::WriteLine("[managed] sending delegate as callback...");

// force garbage collection cycle to prove
// that the delegate doesn't get disposed
GC::Collect();

int answer = TakesCallback(cb, 243, 257);

// release reference to delegate
gch.Free();
}

调用 GCHandle::Alloc() 应该是为了防止垃圾收集器收集委托(delegate)。但我的理解是,变量 GetTheAnswerDelegate^ fp 已经使委托(delegate)保持事件状态,因为它是一个根对象,即使我删除了对 GCHandle 的调用,该示例仍然有效。仅当我像这样内联委托(delegate)实例化时:

IntPtr ip = Marshal::GetFunctionPointerForDelegate(gcnew GetTheAnswerDelegate(GetNumber));

然后我看到崩溃。

那么 Microsoft 的示例是错误的还是我遗漏了什么?

最佳答案

您忽略了使用调试器对局部变量生命周期的影响。在附加调试器的情况下,抖动标记使用中的变量,直到方法结束。使调试可靠很重要。然而,这也会阻止 GC.Collect() 调用收集委托(delegate)对象。

当您在没有调试器的情况下运行程序的发布版本时,此代码将崩溃。

有关调试构建行为对垃圾收集器的影响的深入解答可在 this post 中找到。

关于c# - 防止委托(delegate)被垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16544511/

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