B
Brian Gideon
How have you handled the finalization of thread-specific unmanaged
resources?
My question pertains specifically to using the DDEML which is a
thread-specific API. In other words, every call to the API using the
same handle must be made on the same thread as the one that obtained
the handle. Obviously, there is a conflict with the GC and the
finalizer thread in cases where the programmer forgets to call Dispose
on a wrapper class.
I have a solution that I have been using for 3 or 4 years now and it
seems to work, but to be honest I'm not positive that it is the right
one. I'm just now beginning to explore the pitfalls of finalization on
thread-specific resources in a careful manner.
Basically what I have is this:
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Cleanup managed resources.
}
if (Thread.CurrentThread.ManagedThreadId == knownThreadId)
{
DdeDisconnect(handle);
}
else
{
PostThreadMessage(knownThreadId, WM_MYUSERMSG, handle,
IntPtr.Zero);
}
}
}
Of course, I have to install an IMessageFilter on the target thread
first. The implementation would be:
bool IMessageFilter.PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MYUSERMSG)
{
DdeDisconnect(m.wParam);
return true;
}
return false;
}
It seems clean, but there are situations where DdeDisconnect will never
be called and I realize that. In most circumstances this seems to work
well.
resources?
My question pertains specifically to using the DDEML which is a
thread-specific API. In other words, every call to the API using the
same handle must be made on the same thread as the one that obtained
the handle. Obviously, there is a conflict with the GC and the
finalizer thread in cases where the programmer forgets to call Dispose
on a wrapper class.
I have a solution that I have been using for 3 or 4 years now and it
seems to work, but to be honest I'm not positive that it is the right
one. I'm just now beginning to explore the pitfalls of finalization on
thread-specific resources in a careful manner.
Basically what I have is this:
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Cleanup managed resources.
}
if (Thread.CurrentThread.ManagedThreadId == knownThreadId)
{
DdeDisconnect(handle);
}
else
{
PostThreadMessage(knownThreadId, WM_MYUSERMSG, handle,
IntPtr.Zero);
}
}
}
Of course, I have to install an IMessageFilter on the target thread
first. The implementation would be:
bool IMessageFilter.PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MYUSERMSG)
{
DdeDisconnect(m.wParam);
return true;
}
return false;
}
It seems clean, but there are situations where DdeDisconnect will never
be called and I realize that. In most circumstances this seems to work
well.