Hier geht es um die Kommunikation zwischen C++
(gemeinsam genutzter Code verschiedener Plattformen) mit C#
(Windows Universal App). Wir wissen, dass der folgende Funktionsaufruf von C++
bis C#
erfolgt.Wie warten wir auf C# asynchrone Delegatenfunktion 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 ...
}
}
oben Das ist sehr einfach. Aber das Problem ist, dass diese Zeichenfolge GetSomeValueEvent()
in C#
eine schwere Aufgabe wie Lesen von Daten aus der Datenbank, und ich muss es async
machen.
async Task<string> GetSomeValueEvent() {
// Some other stuff ...
return "Hello World";
}
Jetzt kommt die Frage: Wie kann ich meine C++
Code Warten auf die Rückkehr dieses Delegatfunktion? In einem anderen Wort, auf was sollte die folgende Unterschrift geändert werden?
public delegate Platform::String GetSomeValueEventHandler();
Ich habe googeln und kann nicht die richtige Terminologie für dieses Problem finden. Wenn Sie sicher sind, dass es unmöglich ist, wäre zumindest schön zu wissen.
Schließlich, ist es das, was wir tun:
string GetSomeValueEvent() {
// Convert a async method to non-async one
var val = someAsyncMethod().Result;
// Some other stuff ...
return "Hello World";
}
Sie müssen sicherstellen, dass GetSomeValueEvent
nicht auf dem Haupt-Thread-Deadlock zu verhindern läuft.
Dieser Fehler tritt auf, wenn Sie zwei Ereignisteilnehmer haben, da nur einer von ihnen für den Rückgabewert verwendet wird. Die Klasse wartet auf den Abschluss nur einer Teilnehmeraufgabe. Besser ist es, das Deferral-Muster zu verwenden. –
@ RaymondChen Ich stimme zu, ich hätte es erwähnen sollen. Aber die Rückgabe eines Wertes aus einem Event-Handler ist eine wirklich schlechte Idee und ich weiß ehrlich gesagt nicht, wie die Verwendung des Deferral-Patterns das auflösen wird. –
Das Windows-Laufzeitmuster soll einen 'EventArgs'-Parameter übergeben, der eine' GetDeferral'-Methode und einen Mechanismus zum Melden von Ergebnissen aufweist. Jeder Delegat nimmt eine Zurückstellung, führt seine asynchrone Arbeit aus, meldet das Ergebnis über den Berichterstellungsmechanismus (möglicherweise eine "SetResult" -Methode oder durch Anhängen des Ergebnisses an eine Sammlung) und schließt dann die Verzögerung ab. Wenn die letzte Verzögerung abgeschlossen ist, überprüft der Aufrufer alle berichteten Ergebnisse. –