gpt4 book ai didi

c# - 防止 GC 在 C# 中接受我的委托(delegate)

转载 作者:搜寻专家 更新时间:2023-10-31 01:06:28 25 4
gpt4 key购买 nike

我指的是我很久以前发表的一篇文章,因为我刚刚开始使用这个 WRG305API.dll。

引用:calling C++ functions containing callbacks in C#

我一直在尝试编写一个与此 DLL 交互的应用程序,感谢当时帮助过我的人。我已经能够让它在短时间内正常工作。

我被这个恼人的问题阻止了,它被描述为:

A callback was made on a garbage collected delegate of type 'WinFFT!WinFFT.winradioIO.winRadioIOWrapper+CallbackFunc::Invoke'. This may cause application crashes ...

这是封装代码:

using System;
using System.Collections.Generic;
using System.Text;

using System.Runtime.InteropServices;

namespace WinFFT.winradioIO
{
class winRadioIOWrapper
{
private const string APIDLL_PATH = "WRG305API.dll";

public delegate void CallbackFunc(IntPtr p);

public CallbackFunc mycallback;

[StructLayout(LayoutKind.Sequential)]
public struct Features
{
public uint feature;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RadioInfo
{
public uint length;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string serialNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string productName;
public UInt64 minFrequency;
public UInt64 maxFrequency;
public Features feature;
}

[DllImport(APIDLL_PATH)]
public static extern int OpenRadioDevice(int deviceNumber);

[DllImport(APIDLL_PATH)]
public static extern bool CloseRadioDevice(int radioHandle);

[DllImport(APIDLL_PATH)]
public static extern int GetRadioList(ref RadioInfo info, int bufferSize, ref int infoSize);

[DllImport(APIDLL_PATH)]
public static extern bool IsDeviceConnected(int radioHandle);

[DllImport(APIDLL_PATH)]
public static extern bool GetInfo(int radioHandle, ref RadioInfo info);

[DllImport(APIDLL_PATH)]
public static extern int GetFrequency(int radioHandle);

[DllImport(APIDLL_PATH)]
public static extern bool SetFrequency(int radioHandle, int frequency);

[DllImport(APIDLL_PATH)]
private static extern bool CodecStart(int hRadio, CallbackFunc func, IntPtr CallbackTarget);

[DllImport(APIDLL_PATH)]
private static extern uint CodecRead(int hRadio, byte[] Buf, uint Size);

[DllImport(APIDLL_PATH)]
private static extern bool CodecStop(int hRadio);


public static bool startIFStream(int radioHandle)
{


bool bStarted = CodecStart(radioHandle, MyCallbackFunc, IntPtr.Zero);
return bStarted;
}

// Note: this method will be called from a different thread!
private static void MyCallbackFunc(IntPtr pData)
{
// Sophisticated work goes here...
}

public static void readIFStreamBlock(int radioHandle, byte[] streamDumpLocation, uint blockSize)
{
CodecRead(radioHandle, streamDumpLocation, blockSize);
}

public static bool stopIFStream(int radioHandle)
{
bool bStoped = CodecStop(radioHandle);
return bStoped;
}
}
}

这是我的应用程序接口(interface)类层,它提供了使用 dll 接口(interface)的友好方法:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace WinFFT.winradioIO
{
class radioInterface
{
enum DeviceStatus { Disconnected, Connected, Unknown };
private static DeviceStatus deviceStatus = DeviceStatus.Unknown;

public static string radioName, serialNumber;
public static int minimumFreq, maximumFreq;

static int radioHandle;

static radioInterface()
{
InitializeDeviceConnection();
}

public static void duffMethod(IntPtr ptr)
{
}

private static void InitializeDeviceConnection()
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);

deviceStatus = DeviceStatus.Disconnected;

// Get Radio Info
winRadioIOWrapper.RadioInfo radioInfo = new winRadioIOWrapper.RadioInfo();
int aStructSize = Marshal.SizeOf(radioInfo), anInfoSize = 0;
radioInfo.length = (uint)aStructSize;

if (winRadioIOWrapper.GetRadioList(ref radioInfo, aStructSize, ref anInfoSize) == 1)
{
radioName = radioInfo.productName;
serialNumber = radioInfo.serialNumber;

minimumFreq = (int)radioInfo.minFrequency;
maximumFreq = (int)radioInfo.maxFrequency;
}

// Open device
radioHandle = winRadioIOWrapper.OpenRadioDevice(0);

CheckDeviceConnection();
}

private static void CheckDeviceConnection()
{
bool anIsDeviceConnected = winRadioIOWrapper.IsDeviceConnected(radioHandle);

if (deviceStatus == DeviceStatus.Unknown ||
deviceStatus == DeviceStatus.Disconnected && anIsDeviceConnected ||
deviceStatus == DeviceStatus.Connected && !anIsDeviceConnected)
{
if (anIsDeviceConnected)
{
deviceStatus = DeviceStatus.Connected;

winRadioIOWrapper.startIFStream(radioHandle);

}
else
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);

deviceStatus = DeviceStatus.Disconnected;
}
}
}

public static void ReadIFStream(ref byte[] bufferLocation)
{
winRadioIOWrapper.readIFStreamBlock(radioHandle, bufferLocation, (uint)bufferLocation.Length);
}

public static void SetFreq(int valueInHz)
{
winRadioIOWrapper.SetFrequency(radioHandle, valueInHz);
}

public static void ShutDownRadio()
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);
}

}
}

我明白为什么AVIDeveloper选择了这条路,它从WinRadio Reciever(这就是DLL的用途)连续流出数据非常棒,但是DLL中的CodecRead函数允许复制指定数量的字节从 radio 的缓冲区。这是我走的路,因为我想控制我获取数据的频率,因此我单独留下委托(delegate)函数的原因。但就目前的情况而言,我正在将包装器中的委托(delegate)丢给 GC,我真的很困惑如何防止这种情况发生。

在此先感谢大家。

最佳答案

将委托(delegate)存储为字段。

private static CallbackFunc _callback = new CallbackFunc(MyCallbackFunc);

public static bool startIFStream(int radioHandle)
{


bool bStarted = CodecStart(radioHandle, _callback, IntPtr.Zero);
return bStarted;
}

关于c# - 防止 GC 在 C# 中接受我的委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20735085/

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