我有一个WPF应用程序,我们使用DDE(动态数据交换)打开Avaya拨号程序。它可以发射两到三次,但是当我们第四次发射时,有时经过很长的间隙,我发现下面的错误。
“对类型为”NDde!NDde.Foundation.Ddeml + DdeCallback :: Invoke'“的垃圾收集委托进行了回调。这可能会导致应用程序崩溃,损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须将它们保持活动状态,直到确保它们永远不会被调用为止。“
以下是此代码。您可以在https://ndde.codeplex.com/中找到完整代码 请帮我找到根本原因并解决它。
//call back declared here
internal static class Ddeml
{
public delegate IntPtr DdeCallback(
int uType, int uFmt, IntPtr hConv, IntPtr hsz1, IntPtr hsz2, IntPtr hData, IntPtr dwData1, IntPtr dwData2);
}
internal sealed class DdemlContext : IDisposable
{
private int _InstanceId = 0; // DDEML instance identifier
private Ddeml.DdeCallback _Callback = null ;
public DdemlContext()
{
// Create the callback that will be used by the DDEML.
_Callback = new Ddeml.DdeCallback(this.OnDdeCallback);
}
private IntPtr OnDdeCallback(int uType, int uFmt, IntPtr hConv, IntPtr hsz1, IntPtr hsz2, IntPtr hData, IntPtr dwData1, IntPtr dwData2)
{
// Create a new transaction object that will be dispatched to a DdemlClient, DdemlServer, or ITransactionFilter.
DdemlTransaction t = new DdemlTransaction(uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
// Run each transaction filter.
foreach (IDdemlTransactionFilter filter in _Filters)
{
if (filter.PreFilterTransaction(t))
{
return t.dwRet;
}
}
// Dispatch the transaction.
switch (uType)
{
case Ddeml.XTYP_ADVDATA:
{
DdemlClient client = _ClientTable[hConv] as DdemlClient;
if (client != null)
{
if (client.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_ADVREQ:
{
DdemlServer server = _ServerTable1[hConv] as DdemlServer;
if (server != null)
{
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_ADVSTART:
{
DdemlServer server = _ServerTable1[hConv] as DdemlServer;
if (server != null)
{
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_ADVSTOP:
{
DdemlServer server = _ServerTable1[hConv] as DdemlServer;
if (server != null)
{
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_CONNECT:
{
// Get the service name from the hsz2 string handle.
StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE);
int length = Ddeml.DdeQueryString(_InstanceId, hsz2, psz, psz.Capacity, Ddeml.CP_WINANSI);
string service = psz.ToString();
DdemlServer server = _ServerTable2[service] as DdemlServer;
if (server != null)
{
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_CONNECT_CONFIRM:
{
// Get the service name from the hsz2 string handle.
StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE);
int length = Ddeml.DdeQueryString(_InstanceId, hsz2, psz, psz.Capacity, Ddeml.CP_WINANSI);
string service = psz.ToString();
DdemlServer server = _ServerTable2[service] as DdemlServer;
if (server != null)
{
_ServerTable1[hConv] = server;
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_DISCONNECT:
{
DdemlClient client = _ClientTable[hConv] as DdemlClient;
if (client != null)
{
_ClientTable[hConv] = null;
if (client.ProcessCallback(t))
{
return t.dwRet;
}
}
DdemlServer server = _ServerTable1[hConv] as DdemlServer;
if (server != null)
{
_ServerTable1[hConv] = null;
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_EXECUTE:
{
DdemlServer server = _ServerTable1[hConv] as DdemlServer;
if (server != null)
{
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_POKE:
{
DdemlServer server = _ServerTable1[hConv] as DdemlServer;
if (server != null)
{
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_REQUEST:
{
DdemlServer server = _ServerTable1[hConv] as DdemlServer;
if (server != null)
{
if (server.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_XACT_COMPLETE:
{
DdemlClient client = _ClientTable[hConv] as DdemlClient;
if (client != null)
{
if (client.ProcessCallback(t))
{
return t.dwRet;
}
}
break;
}
case Ddeml.XTYP_WILDCONNECT:
{
// This library does not support wild connects.
return IntPtr.Zero;
}
case Ddeml.XTYP_MONITOR:
{
// Monitors are handled separately in DdemlMonitor.
return IntPtr.Zero;
}
case Ddeml.XTYP_ERROR:
{
// Get the error code, but do nothing with it at this time.
int error = dwData1.ToInt32();
return IntPtr.Zero;
}
case Ddeml.XTYP_REGISTER:
{
if (Register != null)
{
// Get the service name from the hsz1 string handle.
StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE);
int length = Ddeml.DdeQueryString(_InstanceId, hsz1, psz, psz.Capacity, Ddeml.CP_WINANSI);
string service = psz.ToString();
Register(this, new DdemlRegistrationEventArgs(service));
}
return IntPtr.Zero;
}
case Ddeml.XTYP_UNREGISTER:
{
if (Unregister != null)
{
// Get the service name from the hsz1 string handle.
StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE);
int length = Ddeml.DdeQueryString(_InstanceId, hsz1, psz, psz.Capacity, Ddeml.CP_WINANSI);
string service = psz.ToString();
Unregister(this, new DdemlRegistrationEventArgs(service));
}
return IntPtr.Zero;
}
}
return IntPtr.Zero;
}