Frage zu Asynchronen Aufruf eines Delegates **gelöst**
-
ich habe deinen Post gelesen und möchte nun gern EndInvoke rufen doch ohne meine Thread zu blockieren.
MfG
-
In deinem Event Handler (ev. via IAsyncResult).
Simon
-
den hat je der nutzer der Dll und der vergisst das ja im zweifel.
ich möchte das sicher haben.
MfG
-
Also ich hab das jetzt mal mit dem AsyncHandler probiert
using namespace System; namespace TestNamspace { public delegate void TestAA(unsigned char Test11, unsigned char Test12,unsigned char Test13); public void Program_TestAAEvent(unsigned char Test11, unsigned char Test12,unsigned char Test13){} public ref class CTestClass { private: AsyncCallback ^OnAsyncHandler; static void AsyncHandlerCallback(IAsyncResult ^result) { ((CTestClass^)result->AsyncState)->AsyncHandler(result); } void AsyncHandler(IAsyncResult ^result) { System::Runtime::Remoting::Messaging::AsyncResult ^AsyncResult; AsyncResult = (System::Runtime::Remoting::Messaging::AsyncResult ^)result; if (TestAADelegate = AsyncResult->AsyncDelegate) { ((TestAA ^)AsyncResult->AsyncDelegate)->EndInvoke(result); } } public: TestAA ^TestAADelegate; CTestClass() { TestAADelegate += gcnew TestAA(Program_TestAAEvent); OnAsyncHandler = gcnew AsyncCallback(&TestNamspace::CTestClass::AsyncHandlerCallback); TestAADelegate->BeginInvoke(5,4,3,AsyncCallback ^OnAsyncHandler,this); } } }
jetzt möchte ich diesen Handler aber für all meine Delegates verwenden um Endinvoke aufzurufen. Geht auch da ich im Handler ja immer wieder mit if fragen kann um den richtigen Cast auszuführen
if (TestAADelegate = AsyncResult->AsyncDelegate) { ((TestAA ^)AsyncResult->AsyncDelegate)->EndInvoke(result); } else if (...) { } else if (...) // usw.
kann man nicht das über einen allgemeinen Cast lösen so etwa?
((Delegate ^)AsyncResult->AsyncDelegate)->EndInvoke(result);
hier kommt die Meldung: error C2039: 'EndInvoke': Ist kein Element von 'System::Delegate'
aber gibt es nihct eine von Delegate abgeleitete Klasse die Endinvoke als Member hat von der dann meine Delegates abgeleitet werden mit der ich das machen kann?
-
bei MulticastDelegate
((MulticastDelegate ^)AsyncResult->AsyncDelegate)->EndInvoke(result);
kommt auch die Fehlermeldung:
hier kommt die Meldung: error C2039: 'EndInvoke': Ist kein Element von 'System::MulticastDelegate'obwohl unter Hilfe steht das diese Funktionen bereitgestellt werden sie tauchen nur nicht als Member auf.
Auf welche Klasse muß ich casten?
-
Hat keiner eine Idee welche Klasse man verwenden muß, die von Delegate abgeleitet ist und Endinvoke als Member enthält?
-
in Visual Basic geht das
Action.BeginInvoke(New AsyncCallback(AddressOf Action.EndInvoke), _ Nothing)
http://www.activevb.de/tipps/vbnettipps/tipp0003.html
wieso geht das in C++ nicht?
TestAADelegate->BeginInvoke(5,4,3,gcnew AsyncCallback(&TestAADelegate->EndInvoke),nullptr);
er meldet:
error C2276: '&': Ungültige Operation auf Ausdruck einer gebundenen Memberfunktion
error C3350: "System::AsyncCallback": Ein Delegatkonstruktor erwartet 2 Argument(e)
-
TestAADelegate->BeginInvoke(5,4,3,gcnew AsyncCallback(&TestAADelegate->EndInvoke),nullptr);
Was ist denn hier der Handler für EndInvoke? Da sollte doch was hinterlegt sein, sonst macht es ja keinen Sinn, ihn überhaupt anzugeben.
-
EndInvoke ist eine Memberfunktion des Delegates, die existiert automatisch
-
Und was macht die, ausser nichts?
Es sollte wenn dann lauten:
TestAADelegate->BeginInvoke(5,4,3,gcnew AsyncCallback(&TestAADelegate::EndInvoke),nullptr);
So wie ich das sehe, liefert Endinvoke einen Rückgabe-Wert, der ausgewertet werden kann und vom Delegat-Typ abhängig ist.
Nebenbei: Daher sollte schon kein Mulicast-Delegat verwendet werden, weil sonst nicht klar ist, welcher Rückgabewert eigentlich zurückgegeben wird.
Deshalb wird es auch generell nicht mit dem allgemeinen Delegate ^ funktionieren, weil EndInvoke immer von einem speziellen Delegattyp ist, der für EndInvoke vorgesehen ist.
-
TestAADelegate->BeginInvoke(5,4,3,gcnew AsyncCallback(&TestAADelegate::EndInvoke),nullptr);
da kommen dann die Fehlermeldungen
error C2065: 'EndInvoke': nichtdeklarierter Bezeichner
error C3350: "System::AsyncCallback": Ein Delegatkonstruktor erwartet 2 Argument(e).
-
Das bedeutet ja meiner Meinung nach, dass EndInvoke einen speziellen Handler mit einem speziellen Delegaten braucht, damit das ganze funktioniert.
Mir ist immer noch nicht der Sinn klar, den Du mit einem solchen Aufruf bezweckts.
Willst Du jetzt ein EndInvoke oder willst Du keines?
-
ich möchte das nachdem meine delegate funktion fertig ist automatisch EndInvoke aufgerufen wird und da der Asynchrone Handler nunmal automatisch aufgerufen wird hab ich gedacht, dasss ich im doch auch EndInvoke übergeben kann.
-
Versuch es mal so:
void AsyncHandler(IAsyncResult ^result) { System::Runtime::Remoting::Messaging::AsyncResult ^AsyncResult; AsyncResult = (System::Runtime::Remoting::Messaging::AsyncResult ^)result; Console::WriteLine("Bin im CTestClass asynchronen Ende-Handler"); /*if (TestAADelegate = AsyncResult->AsyncDelegate) { ((TestAA ^)AsyncResult->AsyncDelegate)->EndInvoke(result); }*/ //IAsyncResult ^res; this->TestAADelegate->EndInvoke(result); }
-
wenn du oben die vorherigen Posts gelesen hättest wüßtest du das es das geht.
Ich möchte es aber vereinfachen und deshalb hab ich im netz dieses VB beispiel gesehen und wollte dieses auf C++ übertragen, da das normalerweise ebenfalls geht.
-
Funktionierts jetzt oder nicht?
-
also mit der Anweisung
TestAADelegate->BeginInvoke(5,4,3,gcnew AsyncCallback(&TestNamespace::TestAADelegate::EndInvoke),nullptr);
kommt nur noch die Fehlermeldung:
error C3352: "void TestNamespace::TestAADelegate::EndInvoke(System::IAsyncResult ^)": Die angegebene Funktion stimmt nicht mit dem Delegattyp "void (System::IAsyncResult ^)" überein.
obwohl beides ja die selben Typen sind.
-
Ist ja auch klar, weil der Prototy für AsyncCallback folgendermaßen aussieht:
[SerializableAttribute] [ComVisibleAttribute(true)] public delegate void AsyncCallback ( IAsyncResult^ ar )
EndInvoke passt da leider nicht.
Ich poste dir mal mein eigens Beispiel, da funktionierts:
#include "stdafx.h" using namespace System; using namespace System::Threading; public delegate void TestAA(unsigned char Test11, unsigned char Test12,unsigned char Test13); void Program_TestAAEvent(unsigned char Test11, unsigned char Test12, unsigned char Test13) { Console::WriteLine("Bin im globalen asynchronen Handler vor Sleep"); Thread::Sleep(1000); Console::WriteLine("Bin im asynchronen Handler nach Sleep"); } public ref class CTestClass { private: AsyncCallback ^OnAsyncHandler; static void AsyncHandlerCallback(IAsyncResult ^result) { Console::WriteLine("Bin im asynchronen Callback"); ((CTestClass^)result->AsyncState)->AsyncHandler(result); } void AsyncHandler(IAsyncResult ^result) { System::Runtime::Remoting::Messaging::AsyncResult ^AsyncResult; AsyncResult = (System::Runtime::Remoting::Messaging::AsyncResult ^)result; Console::WriteLine("Bin im CTestClass asynchronen Ende-Handler"); this->TestAADelegate->EndInvoke(result); } public: TestAA ^TestAADelegate; CTestClass() { TestAADelegate += gcnew TestAA(Program_TestAAEvent); OnAsyncHandler = gcnew AsyncCallback(CTestClass::AsyncHandlerCallback); } void StartAsync(int a, int b, int c) { IAsyncResult ^res = TestAADelegate->BeginInvoke(a, b, c, OnAsyncHandler, this); } }; int main(array<System::String ^> ^args) { Console::WriteLine(L"Asynchrone Events"); CTestClass ^testClass = gcnew CTestClass(); testClass->StartAsync(1, 2, 3); Thread::Sleep(5000); return 0; }
-
also dein Beispiel hatte ich schon am Freitag gepostet:
using namespace System; namespace TestNamspace { public delegate void TestAA(unsigned char Test11, unsigned char Test12,unsigned char Test13); public void Program_TestAAEvent(unsigned char Test11, unsigned char Test12,unsigned char Test13){} public ref class CTestClass { private: AsyncCallback ^OnAsyncHandler; static void AsyncHandlerCallback(IAsyncResult ^result) { ((CTestClass^)result->AsyncState)->AsyncHandler(result); } void AsyncHandler(IAsyncResult ^result) { System::Runtime::Remoting::Messaging::AsyncResult ^AsyncResult; AsyncResult = (System::Runtime::Remoting::Messaging::AsyncResult ^)result; if (TestAADelegate == AsyncResult->AsyncDelegate) { ((TestAA ^)AsyncResult->AsyncDelegate)->EndInvoke(result); } } public: TestAA ^TestAADelegate; CTestClass() { TestAADelegate += gcnew TestAA(Program_TestAAEvent); OnAsyncHandler = gcnew AsyncCallback(&TestNamspace::CTestClass::AsyncHandlerCallback); TestAADelegate->BeginInvoke(5,4,3,AsyncCallback ^OnAsyncHandler,this); } } }
EndInvoke passt nicht wegen des Rückgabetypes? Warum passt es dann in VB?
-
Ich glaube wir reden aneinander vorbei.
Ich weiß nicht, warum es in VB funktioniert und in C++/CLI nicht. Tatsache ist, dass es so nicht funktioniert, wie Du es gepostet hat. Aber es funktioniert, wie ich es gepostet habe.
Erklär mir bitte mal, was der Grund ist, dass Du unbedingt das VB Beispiel zum Laufen bringen willst. Dann verstehe ich dich vielleicht.