.net COM-взаимодействие не направляет все COM-сообщения непосредственно обратно к вызывающей стороне. Если вы вызвали COM из STA, он не поймет, как ваше приложение может справиться с повторным входом. Это означает, что сообщения об ошибках, которые могут быть обработаны с повторной попыткой, в конечном итоге вызывают исключения.
Попробуйте реализовать интерфейс IMessageFilter . Это позволит COM понять, как передавать сообщения обратно в ваше приложение. В частности, реализуйте RetryRejectedCall и проверьте, указывают ли ошибки и, возможно, возвращают ли значение тайм-аута (что-то вроде 1000 мс), чтобы COM мог повторить попытку после короткой паузы.
Это тип COM, поэтому этот код вам понадобится для определения интерфейса:
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000016-0000-0000-C000-000000000046")]
public interface IMessageFilter
{
[PreserveSig]
int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType);
[PreserveSig]
int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType);
}
И это пример того, как вы бы это реализовали:
public class MyMessageFilter : IMessageFilter
{
int IMessageFilter.HandleInComingCall(int dwCallType, IntPtr hTaskCaller,int dwTickCount, IntPtr lpInterfaceInfo)
{
// 0 means that it's handled.
return 0;
}
int IMessageFilter.RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType)
{
// The return value is the delay (in ms) before retrying.
return 1000;
}
int IMessageFilter.MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
{
// 1 hear means that the message is still not processed and to just continue waiting.
return 1;
}
}
После того, как вы внедрили фильтр сообщений, вам необходимо зарегистрировать его, используя CoRegisterMessageFilter . Это регистрация для каждого потока, поэтому знайте, в каком потоке вы ее вызываете. Подпись PInvoke: :
[DllImport("ole32.dll")]
static extern int CoRegisterMessageFilter(IMessageFilter lpMessageFilter, out IMessageFilter lplpMessageFilter);
Даже если это не сработает, по крайней мере, если вы зарегистрируете все сообщения в фильтре, вы должны получить дополнительную информацию о том, что идет не так. Посмотрите на значения параметров, передаваемых в фильтр сообщений. Если вы посмотрите их, они будут относиться к кодам ошибок / состояний.
[Помните, что IMessageFilter, о котором я здесь говорю, отличается от System.Windows.Forms.IMessageFilter , поэтому убедитесь, что вы случайно не используете winforms.]