Frage zu Asynchronen Aufruf eines Delegates **gelöst**



  • Hi,

    ich habe in C# einen asynchronen Aufruf einer Delegatfunktion

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using System.Runtime.Remoting.Messaging;
    
    namespace ConsoleApplicationEvent
    {
        class Program
        {
            public delegate void TestAA(byte Test11);
            static event TestAA TestAAEvent;
    
            static void Program_TestAAEvent(byte Test11)
            {
                Thread.Sleep(5000);
                Console.WriteLine("Event");
            }
    
            static void Main(string[] args)
            {
                TestAAEvent += new TestAA(Program_TestAAEvent);
    
                TestAAEvent.BeginInvoke(new byte(),null, null);
    
                Console.WriteLine("Main");
    
                Console.ReadKey();
            }
        }
    }
    

    wie siht dieser Code in C++ aus?

    public delegate void TestAA(unsigned char Test11);
     static event TestAA ^TestAAEvent;
     TestAAEvent += gcnew TestAA(Program_TestAAEvent);
     TestAAEvent->BeginInvoke(5,null, null); // ?????????????????????????
    

    speziell geht es um die Frage wie sieht der Asynchrone Aufruf mit BeginInvoke aus?

    MfG



  • BeginInvoke gibts anscheinend nicht.

    Wenn dem so ist wird du im registrierten EventHandler einen Bachgoundworker für den eigentlichen Eventhandler starten müssen, damit er asynchron abläuft.

    Es ist aber so in deinem Code, dass Du ein Event außerhalb der Klasse getriggert hast. Somit könntest Du gleich einen Backgroundworker laufen lassen ohne den Umweg über das Event. Events eigenen sich eher, um bestimmte innere Aktionen der Klasse über den Eventhandler mitzubekommen.



  • @taraneas

    BeginInvoke gibts anscheinend nicht.

    Wie kommst Du darauf?

    @Destiniy
    Du solltest auch EndInvoke(..) aufrufen, ansonsten können Resourcen Lecks entstehen.

    Und was ist genau deine Frage?
    Was geht nicht? Compiler Error? Linker Error? Unerwünschtes Verhalten?

    wie siht dieser Code in C++ aus?

    Ganz schlecht, denn das ist kein C++ sondern C++/CLI.

    Simon



  • also wenn ich:

    public delegate void TestAA(unsigned char Test11, unsigned char Test12,unsigned char Test13);
    
    TestAAEvent->BeginInvoke(5,4,3,NULL,NULL);
    

    meint der

    error C2664: ::BeginInvoke': Konvertierung des Parameters 4 von 'int' in 'System::AsyncCallback ^' nicht möglich

    Wie sieht der Aufruf in C++ denn aus und wo muß die Funktion EndInvoke hin?



  • Ich habs mal schnell ausprobiert und Intellisense hat nichts angezeigt. Deshalb hab ich ein "anscheinend" dazugefügt, weil ich in der Doku nicht nachgeschlaut habe.

    Dann sieht der Code in C++/CLI so aus:

    TestAAEvent->BeginInvoke(5, nullptr, nullptr);
    


  • jetzt meldet er bei

    public delegate void TestAA(unsigned char Test11, unsigned char Test12,unsigned char Test13); 
    
    TestAAEvent->BeginInvoke(5,4,3,nullptr,nullptr);
    

    error C3918: Für die Syntax muss "TestAAEvent" ein Datenmember sein.



  • Wie sieht denn der komplette Code aus?



  • 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
      {
        public:
          event TestAA ^TestAAEvent;
    
          CTestClass()
          {
            TestAAEvent += gcnew TestAA(Program_TestAAEvent);
            TestAAEvent->BeginInvoke(5,4,3,nullptr,nullptr);
          }
      }
    }
    

    da ist das Projekt jetzt nur auf das nötigste reduziert. Das ist ein Dll Projekt wo die instanzieierung des events durch den Nutzer der Dll vorgenommen wird.

    TestAAEvent += gcnew TestAA(Program_TestAAEvent);
    

    Aber zum testen müßte es auch so gehen.

    MfG



  • Du sollst kein Event machen sagt Dir der Compiler.
    Also anstelle von event TestAA... einfach TestAA...

    Da Du ja dann den Event doch willst musst Du ihn halt weiterleiten.

    Simon



  • Da ist theta mal wieder schneller gewesen.

    Du bringst es zum Laufen, wenn Du kein Event verwendest, sondern ein normales Delegat. Für diesen Zweck ist das Event eh nicht sinnvoll, weil du im Inneren der Klasse den Handler hinzunimmst. Wie gesagt, Events eigenen sich dazu, Handler von außerhalb der Klasse hinzuzunehmen und von Innen zu triggern. Da macht es auch keinen Sinn, das asynchron zu machen, weil man im Code sicher sein will, dass der Handler abgelaufen ist, bevor man weitermacht, Das ist ja der Sinn des Events, das bestimmte Dinge erledigt werden, bevor im normalen Code weitergemacht wird. Da würde ein ziemliches Durcheinander entstehen, wenn z.B. in den Forms die Events aynchron abgearbeitet würden, da kann sich kein Handler sicher sein kann, dass bestimmte Dinge schon erledigt sind, bzw. könnte auf bestimmte Dinge zeitgleich geschrieben und gelesen werden.

    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
      {
        public:
          //event TestAA ^TestAAEvent;
          TestAA ^TestAADelegate;
    
          CTestClass()
          {
            //TestAAEvent += gcnew TestAA(Program_TestAAEvent);
            TestAADelegate += gcnew TestAA(Program_TestAAEvent);
            TestAADelegate->BeginInvoke(5,4,3,nullptr,nullptr);
          }
      }
    }
    


  • Ok danke ohne event so gehts.

    Wie war das jetzt mit dem EndInvoke wo muß das gerufen werden?

    MfG



  • Ok endinvoke gibt mir nur das ergebnis des Asynchronen Aufrufes zurück ist also nicht notwendig.

    MfG



  • Destiniy schrieb:

    Ok endinvoke gibt mir nur das ergebnis des Asynchronen Aufrufes zurück ist also nicht notwendig.

    MfG

    Lies meinen Post und Du siehst, dass das Ergebnis nicht alles ist!
    Simon



  • also ich habe noch ein bischen zu EndInvoke gelesen

    als Wichtiger Hinweis steht da:
    Rufen Sie EndInvoke immer auf, um den asynchronen Aufruf zu beenden.
    (Warum keine Ahnung)

    wenn ich jetzt.

    TestAADelegate += gcnew TestAA(Program_TestAAEvent);
            TestAADelegate->BeginInvoke(5,4,3,nullptr,nullptr);
            TestAADelegate->EndInvoke(nullptr)
    

    dann blockiert dies ja den Thread bis die Asynchrone Methode aufgerufen wurde und ein ergebnis bereitsteht.

    Wie bekomm ich das hin das EndInvoke aufgerufen wird ohne dass mein Thread auf das Ergebnis wartet, da mir dieses egal ist.

    MfG



  • theta schrieb:

    Destiniy schrieb:

    Ok endinvoke gibt mir nur das ergebnis des Asynchronen Aufrufes zurück ist also nicht notwendig.

    MfG

    Lies meinen Post und Du siehst, dass das Ergebnis nicht alles ist!
    Simon

    Lies meinen Post und Du siehst, dass das Ergebnis nicht alles ist!



  • 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?


Anmelden zum Antworten