2012-01-24 13 views
5

Mam problem, w którym nasza aplikacja zawieszona jest na komputerach naszych klientów, na których pracuję od wielu dni bez rozwiązywania problemów. Problem pojawia się dość losowo z tego, co widzieliśmy, nawet jeśli nie jest to prawdą. Klient informuje również, że procesor osiąga szczyt, gdy aplikacja się zawiesi.Powiesić w aplikacji COM z wtyczką C#

Problem polega na tym, że nie mam pojęcia, gdzie aplikacja się zawiesza (zawiesza się). Mamy kilka wtyczek napisanych w C# jako wtyczki dla głównej aplikacji COM.

Udało mi się skłonić klienta do pobrania miniDump z ProcExp na komputerze, na którym wystąpił problem. Jednak nie jestem bardzo zaznajomieni z WinDBG lub MiniDumps albo o to chodzi. Uruchomiłem !analyze -v i !analyze -v -hang, które produkują niektóre dane wyjściowe, w tym stos poniżej. Za to, co potrafię powiedzieć, wygląda na to, że aplikacja przechodzi do jednej z naszych wtyczek C# (CLR), a następnie z powrotem do COM, która powinna być interfejsem z powrotem do głównej aplikacji dostępnej dla wtyczek. Ale co wtedy? Czy można powiedzieć coś więcej z tego stosu?

Główna aplikacja została napisana w VB6, jeśli ma to znaczenie.

0012da70 7e3693e9 7e3693a8 0012daf0 00000000 ntdll!KiFastSystemCallRet 
0012da9c 7e37a43b 0012daf0 00000000 0000000f user32!NtUserPeekMessage+0xc 
0012dac8 7348e6fd 0012daf0 00000000 0000000f user32!PeekMessageA+0xeb 
0012db1c 77532a9c 00d03774 00000000 00000000 msvbvm60!CMsgFilter::MessagePending+0x21f 
0012db60 77532a48 00000102 0012dbec 00000001 ole32!CCliModalLoop::HandlePendingMessage+0x40 
0012dba8 7751eda6 80010116 80010115 00000000 ole32!CCliModalLoop::HandleWakeForMsg+0x46 
0012dbbc 77547297 0012ddf0 00000001 0012dbe8 ole32!CCliModalLoop::BlockFn+0x8b 
0012dc30 0ae8a2fd 00000002 00000001 00000001 ole32!CoWaitForMultipleHandles+0xcf 
0012dc50 0ae8a264 00000000 00000001 00000001 mscorwks!NT5WaitRoutine+0x51 
0012dcbc 0ae8a1c8 00000001 0012ddf0 00000000 mscorwks!MsgWaitHelper+0xa5 
0012dcdc 0af3ccd0 00000001 0012ddf0 00000000 mscorwks!Thread::DoAppropriateAptStateWait+0x28 
0012dd60 0af3cd65 00000001 0012ddf0 00000000 mscorwks!Thread::DoAppropriateWaitWorker+0x13c 
0012ddb0 0ae8c026 00000001 0012ddf0 00000000 mscorwks!Thread::DoAppropriateWait+0x40 
0012de00 0ae90f4c 00000001 05ae5c80 0012de60 mscorwks!Thread::JoinEx+0x86 
0012de10 0b00ea40 00000001 00000001 5bdf0a2d mscorwks!Thread::Join+0x14 
0012de60 0af0b9a7 00000001 0012deb0 0af0ba10 mscorwks!RCWCleanupList::CleanupWrappersInCurrentCtxThread+0x15a 
0012de6c 0af0ba10 001df674 0012df10 5bdf0afd mscorwks!RCW::Initialize+0x78 
0012deb0 0af0b6a7 001df674 0012df10 5bdf0b6d mscorwks!RCW::CreateRCW+0x84 
0012df20 0af0b7b5 00000000 0012df5c 5bdf0b21 mscorwks!COMInterfaceMarshaler::CreateObjectRef+0x45 
0012df6c 0ae892a8 5bdf3065 0012e6c8 0012e6c8 mscorwks!COMInterfaceMarshaler::FindOrCreateObjectRef+0xac 
0012e428 0ae89444 001df658 11a11014 00000001 mscorwks!GetObjectRefFromComIP+0x1ec 
0012e448 0ae894ab 05b3b0a8 001df658 0e896204 mscorwks!UnmarshalObjectFromInterface+0x19 
0012e464 0af164d1 0012e6c8 0012e6ac 0af164c1 mscorwks!InterfaceMarshalerBase::ConvertSpaceNativeToCLR+0x30 
0012e470 0af164c1 0012e748 0012e738 5bdf32e1 mscorwks!DefaultMarshalOverrides<InterfaceMarshalerBase>::ReturnCLRFromNativeRetval+0xb 
0012e6ac 0aeb4bff 11741a76 0012e734 0012e74c mscorwks!RunML+0x9ac 
0012e780 11740172 05ae5c80 0012e7d4 501b6046 mscorwks!CLRToCOMWorker+0x25f 
... 
... Stack begins down here in our main COM application. 

Edit 1: Niektóre myśli, że mam po przeczytaniu niektórych innych stanowisk forum. Wydaje mi się, że powieszenie jest wprowadzane po marshaling typów danych z .NET do COM. Teraz przeczytałem o another problem, który wydawał się pochodzić z faktu, że zmienne lokalne przekazane do metody COM zostały zebrane śmieci, a zatem czas pracy VB6 miał problemy z dealokacją pamięci. Ten inny post nie był dokładnie tym problemem, ale mnie to przypomniało.

W kodzie .NET uniemożliwiającego COM mamy tego typu kodu

void SomeNETMethod(MyObject obj, bool doIt) { 
    string someString = obj.SomeString; 
    this.myComComponent.DoItInCOM(ref someString, ref doIt); // This is where it hangs. 
} 

Czyżby ref bool jak również bezpośrednio z metody do metody przekazany parametr ma nic wspólnego z czymkolwiek? Jak widzisz, potykam się w ciemności tutaj ...

+1

VB6 i gwinty to woda i ogień. Wygląda na zakleszczenie, gdy główny wątek VB6 przestaje pompować pętlę komunikatów. Potrzebujesz debuggera VB6, aby dowiedzieć się, co robi. –

+0

@HansPassant może te problemy wystąpić, mimo że nasze wtyczki C# nie są wielowątkowe? Jedyny "inny" wątek jaki widzę wchodzi tutaj w grę, to wątek GC, ale zakładam, że to nie problem. – lbergnehr

+1

Czy w kodzie VB6 jest wywoływany DoEvents? Jak wskazuje @HansPassant, główny wątek VB6 może nie być kompatybilny z wątkiem C# (szczególnie jeśli ma on jakąkolwiek interakcję WinForm lub WPF), a kilka magii odbywa się za kulisami w kodzie interopowym, aby związać wątki.W przeszłości odkryłem, że wszelkie wywołania DoEvent wywołane z aplikacji VB6, która jest wywoływana z DotNet, ostatecznie doprowadzą do pewnego zawieszenia/zawieszenia. –

Odpowiedz

0

Przejrzyj swoją metodę "DoItInCOM", ponieważ zrzut jądra wskazuje, że wyświetlane jest modalne okno dialogowe (prawdopodobnie w wyniku błędu w wywołaniu metody COM .)

Parametry .NET są poprawnie przekazywane do strony COM. Jeśli używasz niestandardowego C#, możesz napotkać problem z serializacją, ale tak nie jest.

Jeśli umieścimy procedurę obsługi "Przy błędzie" w kodzie VB, prawdopodobnie można pominąć błędy, które mogłyby wygenerować komunikat w wątku interfejsu użytkownika. Jeśli błąd występuje na niższym poziomie (środowisko wykonawcze VB go wyrzuca), musisz rozwiązać ten problem, wprowadzając poprawki do komponentu COM bezpośrednio. Zapoznaj się również z Przeglądarką zdarzeń systemu Windows dla komunikatów origactin VB Runtime w celu uzyskania dalszych informacji.