Frage zu Asynchronen Aufruf eines Delegates **gelöst**
-
Sags doch gleich:
AsyncCallback ^aSyncCB = gcnew AsyncCallback(this->TestAADelegate, &TestAA::EndInvoke); IAsyncResult ^res = TestAADelegate->BeginInvoke(a, b, c, aSyncCB, nullptr);
-
Danke.
Also gibt es bei dem AsyncCallback einen Konstructor mit 2 Variablen. Wäre gut gewesen wenn man sowas in der MSDN finden würde.
-
Es gibt bei jedem Delegat (und AsyncCallback ist ein Delegat) 2 Konstruktoren, weil man statische und globale Funktionen von nichtstatischen Methoden unterscheiden muss. In C# gibt es glaube ich keine globalen Funktionen mehr und in VB wird es ähnlich sein. Dann braucht man auch keine Unterscheidung.
[url]
http://msdn.microsoft.com/de-de/library/system.delegate.delegate(VS.80).aspx
[/url]Aber ob Du EndInvoke als Async-Callback übergibst, das dann am Abschluß des asnchronen Events aufgerufen wird oder ob Du einen eigenen AsyncCallBack definierst, in dem EndInvoke aufgerufen wird, ist letzendlich egal.
-
nicht ganz.
Denn wenn ich in dem AsyncHandler ein if für 100 Delegates bauen muß ist das erstens zeimlich viel aufwand und wenn man mal eine Funktion hinzufügt, darf man nicht vergessen dieses Delegate in den Handler reinzuschreiben.
-
Das habe ich eigentlich die ganze Zeit versucht zu erklären:
public ref class CTestClass { private: AsyncCallback ^OnAsyncHandler; void AsyncHandlerCallback(IAsyncResult ^result) { Console::WriteLine("Bin im asynchronen Callback"); this->TestAADelegate->EndInvoke(result); } public: TestAA ^TestAADelegate; CTestClass() { TestAADelegate += gcnew TestAA(Program_TestAAEvent); OnAsyncHandler = gcnew AsyncCallback(this, &CTestClass::AsyncHandlerCallback); } void StartAsync(int a, int b, int c) { IAsyncResult ^res = TestAADelegate->BeginInvoke(a, b, c, OnAsyncHandler, this); } };
Das eigentlich Problem war, dass Du nicht wußtest, wie man nichtstatische Handler erzeugt. Bei einem statischen Handler (Callback) kann ich natürlich nicht auf Membervariablen zugreifen.
-
nein das war nicht das Problem, denn ich kann ja über den this Pointer in einen nichtstatischen Member meiner Klasse kommen.
Aber deine Variante ist natürlich einefacher, den Handler nichtstatisch machen und this zeiger mit übergeben (Das es die schon gibt find ich gut).
Aber ich wollte ja überhaupt keinen Handler und trotzdem EndInvoke aufrufen.
-
nein das war nicht das Problem, denn ich kann ja über den this Pointer in einen nichtstatischen Member meiner Klasse kommen.
In einer statischen Funktion existiert kein this-Zeiger.
-
dein Beispiel mit statischer funktion:
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); } } }
habe ich schon auf seite 4 mal gepostet
-
Und für was brauchst Du das if in
void AsyncHandler(IAsyncResult ^result) ?
-
wenn ich meinen Asynchronen Handler bei allen meinen 100 verschiedenen Delegates angebe muß ich doch an der Stelle herausfinden von welchem delegate ich komme, damit ich das richtige EndInvoke aufrufen kann.
if (TestAADelegate == AsyncResult->AsyncDelegate) { ((TestAA ^)AsyncResult->AsyncDelegate)->EndInvoke(result); } else if (TestBBDelegate == AsyncResult->AsyncDelegate) { ((TestBB ^)AsyncResult->AsyncDelegate)->EndInvoke(result); } else if (TestCCDelegate == AsyncResult->AsyncDelegate) { ((TestCC ^)AsyncResult->AsyncDelegate)->EndInvoke(result); } // usw.
Aus diesem Grund ist die andere Version ja einfacher:
TestAADelegate->BeginInvoke(5,4,3,gcnew AsyncCallback(TestAADelegate,&TestNamspace::TestAA::EndInvoke),nullptr);}
-
Das Delegat, das BeginInvoke aufruft, sollte auch EndInvoke aufrufen.
Deshalb kannst Du bei Aufruf von BeginInvoke das Delegat übergeben und dementsprechend EndInvoke aufrufen.AsyncState gibt ein Objekt zurück, das dem letzten Parameter der Methode entspricht, die einen asynchronen Vorgang initiiert.
public ref class CTestClass { private: AsyncCallback ^OnAsyncHandler; static void AsyncHandlerCallback(IAsyncResult ^result) { Console::WriteLine("Bin im asynchronen Callback"); //this->TestAADelegate1->EndInvoke(result); TestAA ^del = dynamic_cast<TestAA ^>(result->AsyncState); if (del != nullptr) { del->EndInvoke(result); } } public: TestAA ^TestAADelegate1; TestAA ^TestAADelegate2; CTestClass() { TestAADelegate1 += gcnew TestAA(Program_TestAAEvent); OnAsyncHandler = gcnew AsyncCallback(&CTestClass::AsyncHandlerCallback); } void StartAsync(int a, int b, int c) { IAsyncResult ^res1 = TestAADelegate1->BeginInvoke(a, b, c, OnAsyncHandler, this->TestAADelegate1); IAsyncResult ^res2 = TestAADelegate2->BeginInvoke(a, b, c, OnAsyncHandler, this->TestAADelegate2); } };
Wenn Du lauter unterschiedliche Delegaten benutzt, solltest Du auch unterschiedliche AsyncCallbacks verwenden. Dann ist das if eigentlich überflüssig.
Oder Du verwendest generic delegates. So was wäre auch mal interessant.
-
die Delegates sind aber nicht vom selben Typ, deshalb weiß ich in dem AsyncHandler ja nicht in was ich Casten muß deshalb das if
Wenn ich bei jedem Delegattyp nen anderen Handler bauen wollte wäre das ja noch umständlicher
ich werde die Variante benutzen:
TestAADelegate->BeginInvoke(5,4,3,gcnew AsyncCallback(TestAADelegate,&TestNamspace::TestAA::EndInvoke),nullptr);
da hab ich keine arbeit mit irgendwelchen Asynchronen Handlern und EndInvoke wir auch aufgerufen.
-
Aber jetzt verstehe ich endlich, warum Du unbedingt diese Variante bevorzugst.
Mich hat das Thema interessiert, weil ich mit Sicherheit noch asynchrone Aufrufe von Delegaten benötige. Da habe ich selber einiges gelernt.
-
hab schon gemerkt dafür ist das Forum doch da