Si tratta della comunicazione tra C++
(codice condiviso di piattaforme diverse) con C#
(Windows Universal App). Sappiamo che quanto segue è come facciamo una chiamata di funzione da C++
a C#
.Come attendiamo la funzione di delegato asincrona C# in C++/CX
C#
class FooCS
{
FooCS()
{
FooC c = new ref FooC();
c.m_GetSomeValueEvent = GetSomeValueEvent;
// Some other stuff ...
}
string GetSomeValueEvent()
{
// Some other stuff ...
return "Hello World";
}
}
C++
public delegate Platform::String GetSomeValueEventHandler();
class FooC
{
public:
event GetSomeValueEventHandler^ m_GetSomeValueEvent;
void someFunction(){
Platform::String^ str = m_GetSomeValueEvent();
// Some other stuff ...
}
}
Quanto sopra è molto semplice. Ma il problema è che questa stringa GetSomeValueEvent()
in C#
esegue alcune attività pesanti come la lettura dei dati dal database e devo renderlo async
.
async Task<string> GetSomeValueEvent() {
// Some other stuff ...
return "Hello World";
}
Ora qui viene la domanda: come faccio a fare il mio C++
codice di attesa per il ritorno di questa funzione delegata? In un'altra parola, a cosa dovrebbe essere modificata la seguente firma?
public delegate Platform::String GetSomeValueEventHandler();
Sono stato google e non riesco a trovare la terminologia giusta per questo problema. Se sai per certo che è impossibile, sarebbe almeno bello da sapere.
Alla fine, questo è ciò che facciamo:
string GetSomeValueEvent() {
// Convert a async method to non-async one
var val = someAsyncMethod().Result;
// Some other stuff ...
return "Hello World";
}
È necessario assicurarsi GetSomeValueEvent
non è in esecuzione sul thread principale per evitare stallo.
Questo errore si interrompe quando si dispone di due sottoscrittori di eventi, poiché solo uno di essi verrà utilizzato per il valore restituito. La classe aspetterà che venga completata una sola attività di sottoscrizione. È meglio usare il modello di differimento. –
@RaymondChen Sono d'accordo, avrei dovuto dirlo. Ma restituire un valore da un gestore di eventi è una pessima idea e onestamente non so come risolvere il problema con il rinvio del differimento. –
Il modello di Windows Runtime passa un parametro 'EventArgs' che ha un metodo' GetDeferral' e un meccanismo per la segnalazione dei risultati. Ogni delegato prende un differimento, esegue il suo lavoro asincrono, riporta il risultato tramite il meccanismo di segnalazione (forse un metodo 'SetResult', o aggiungendo il risultato a una raccolta), quindi completando il differimento. Al termine dell'ultimo differimento, il chiamante controlla tutti i risultati riportati. –