У меня есть DLL, написанная на C ++. У меня есть интерфейс IRaster
, который наследуется от интерфейса IUnknown
, и класс Raster
, который реализует интерфейс IRaster
. Я также экспортирую функцию ReadRaster
для возврата указателя на IRaster
.
В C # у меня есть соответствующее определение интерфейса IRaster
и объявление функции для ReadRaster
. Это обычно работает очень хорошо для меня, чтобы использовать IRaster
в C #. Однако функция ReadRaster
занимает много времени, и мне нужно использовать интерфейс в фоновом потоке. Пока я вызываю ReadRaster
в фоновом потоке, я могу использовать возвращенный IRaster
без каких-либо проблем. Иногда мне также нужно использовать интерфейс в основном потоке пользовательского интерфейса. Поскольку это включает передачу интерфейса COM между двумя потоками, это не работает. Один из способов - попробовать маршалинг с перекрестными потоками, который я пробовал немного без какого-либо успеха.
Я также попробовал другой способ избежать перекрестного маршалинга COM-интерфейса. Я экспортирую функцию ReadRasterAsPtr
и ConvertRasterPtrToRaster
в C ++. В фоновом потоке я вызываю ReadRasterPtr
, а затем вызываю ConvertRasterPtrToRaster
в основном потоке пользовательского интерфейса. Этот трюк работает большую часть времени. Однако иногда происходит сбой, что означает, что функция ConvertRasterPtrToRaster
не может вернуть действительный интерфейс IRaster
в C #. Когда это терпит неудачу, неожиданно, и эта проблема беспокоила меня в течение долгого времени.
Спасибо за помощь!
Некоторые коды относятся к проблеме:
В C ++,
interface IRaster:public IUnknown
{
virtual void _stdcall delete()=0;
};
class Raster: public IRaster
{
HRESULT __stdcall QueryInterface(const IID& riid,void **ppvObject) {
if (riid == IID_IUnknown || riid==IID_Raster) {
*ppvObject =(IRaster*)this;
return S_OK;
}
*ppvObject = NULL ;
return E_NOINTERFACE ;
}
ULONG __stdcall AddRef() {
return 1;
}
ULONG __stdcall Release() {
return 1; //I am not using the COM reference counting mechanism and I
delete the COM class manually
}
virtual void _stdcall delete(){
delete this;
}
}
extern "C" __declspec(dllexport) IRaster* __stdcall ReadRaster()
{
IRaster* pRaster=new Raster();
return pRaster;
}
extern "C" __declspec(dllexport) void* __stdcall ReadRasterAsPtr(const char* path)
{
IRaster* pRaster=new Raster();
return (void*)pRaster;
}
extern "C" __declspec(dllexport)IRaster* __stdcall ConvertRasterPtrToRaster (void* pRaster) {
return (IRaster*) pRaster;
}
В C #,
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("2B95F084-ACCB-4642-BC12-E116C00814F9")]
public interface IRaster
{
[PreserveSig]
void Delete();
}
public class Utils{
[DllImport("Base.dll")]
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
public extern static IRaster ReadRaster();
[DllImport("Base.dll")]
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
public extern static IntPtr ReadRasterAsPtr();
[DllImport("Base.dll")]
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
public extern static IRaster ConvertRasterPtrToRaster(IntPtr grdPtr);
}