Domanda

Per farla breve: in un'applicazione C# che funziona con com inproc-server (DLL), incontro "0x80010100: chiamata di sistema non riuscita" Eccezione e in modalità debug anche l'eccezione di contesto.

Ora più nei dettagli:

1) L'app C# inizializza STA, crea un oggetto COM (registrato come "appartamento"); Quindi in abbonati al suo punto di connessione e inizia a lavorare con l'oggetto.

2) Ad un certo punto l'oggetto COM genera molti eventi, passando come argomento una grande raccolta di oggetti COM, che sono creati nello stesso appartamento.

3) Il gestore di eventi sul lato C# elabora la raccolta di cui sopra, chiamando occasionalmente alcuni metodi degli oggetti. Ad un certo punto queste ultime chiamate iniziano a fallire con le eccezioni di cui sopra.

Sul lato com l'appartamento usa una finestra nascosta il cui winproc assomiglia a questo:

typedef std::function<void(void)> Functor;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)   
{   
  switch(msg)   
  {   
    case AM_FUNCTOR:
    {
      Functor *f = reinterpret_cast<Functor *>(lParam);
      (*f)();
      delete f;
    }
    break;   
    case WM_CLOSE:   
      DestroyWindow(hwnd);   
    break;   
    default:   
      return DefWindowProc(hwnd, msg, wParam, lParam);   
  }   
  return 0;   
} 

Gli eventi vengono pubblicati in questa finestra da altre parti del server COM:

void post(const Functor &func)
{
  Functor *f = new Functor(func);
  PostMessage(hWind_, AM_FUNCTOR, 0, reinterpret_cast<LPARAM>(f));
}

Gli eventi sono implementazioni CP ATL standard legate ai parametri effettivi e si riducono a qualcosa del genere:

pConnection->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);

In C# il gestore sembra questo:

private void onEvent(IMyCollection objs)
{
  int len = objs.Count; // usually 10000 - 25000
  foreach (IMyObj obj in objs)
  {
    // some of the following calls fail with 0x80010100
    int id = obj.id;
    string name = obj.name;
    // etc...
  }
}

==================

Quindi, il problema di cui sopra può accadere solo perché la coscia dell'appartamento è troppo carica con gli eventi che cerca di consegnare? O il ciclo del messaggio dovrebbe essere completamente bloccato per causare tale comportamento?

Supponiamo che il controllo del messaggio abbia 2 eventi sequenziali che valutano la chiamata "Onevvent". Il primo entra nel codice gestito da C#, che tenta di rientrare nel codice non gestito, lo stesso appartamento. Di solito, questo è consentito e lo facciamo molto. Quando, in quali circostanze può fallire?

Grazie.

È stato utile?

Soluzione

Questo dovrebbe funzionare anche con più appartamenti previsti da:

  • Solo uno dei thread risponde a eventi esterni come traffico di rete, timer, messaggi pubblicati ecc.
  • Altri thread solo richieste COM di servizio (anche se richiamano il thread principale durante l'elaborazione).

E

  • Nessuna coda di thread si è mai piena, impedendo a COM di comunicare con il thread.

Innanzitutto:Sembra che alcuni oggetti non siano nello stesso appartamento di altri oggetti. Sei sicuro che tutti gli oggetti vengano creati nella STA?

Quello che stai descrivendo è un classico deadlock: due fili indipendenti, ognuno in attesa dall'altro. Questo è ciò che mi aspetterei che si verifichi con quel design che opera con i lati C# e COM su diversi thread.

Dovresti stare bene se tutto Gli oggetti sono sullo stesso thread, così come la finestra nascosta su quel thread, quindi penso che tu debba verificarlo. (Ovviamente questo include tutti gli altri oggetti creati dal lato COM e passati al lato C#.)

Potresti provare a debug questo premendo "Pause" nel debugger e controllando quale codice era in ogni thread (se vedi RPCRT*.dll Questo significa che stai guardando un proxy). In alternativa, è possibile debugprint l'ID thread corrente da vari punti critici in entrambi i lati C# e COM e il tuo WNDPROC - dovrebbero essere tutti uguali.

In secondo luogo: Dovrebbe funzionare con più thread a condizione che solo uno dei thread genera elementi di lavoro, e l'altro non fa altro che oggetti Host com che rispondono alle chiamate (IE non genera chiamate da timer, traffico di rete, messaggi pubblicati ecc.), In In questo caso può darsi che la coda del thread sia piena e che com non possa rispondere a una chiamata.

Invece di usare la coda del thread, è necessario utilizzare un deque protetto da una sezione critica.

Potresti mantenere un contatore di articoli a/fuori dalla coda per vedere se questo è il problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top