Frage zu AutoResetEvent and WaitOne...



  • Hallo Leute,

    ich verwende C# als Erweiterung einer Nativen Anwendung. Diese stellt eine API zur Verfügung welche ich via Interop-Service-Wrapper implementieren. (Das vorab, weiß nicht ob das für meine frage Relevant is:)

    So diese Funktionen sind asyncron, d.h. über ein Callback bekomm ich die Info, funktion fertig ,diesem Callback geb ich eine "AutoResetEvent" mit, welche ich darin setze.

    Pseudo:

    Callback:

    void CAllbackFunc(IntPtr context)
    {
      ( (AutoResetEvent)((GCHandle)context).Target)).Set();
     }
    

    Funktion:

    var waitEvent = new AutoResetEvent(false);
    GCHandle managedContext = GCHandle.Alloc(waitEvent);
    
    //Async call
    MyNativeWrapper.MyFunc((IntPtr)managedContext , _CallbackDelegate,TIMEOUT_VALUE,....);
    
    //Warten bis callback gefeuert wird
    waitEvent.WaitOne(TIMEOUT_VALUE);
    

    Das Problem hierbei ist, dass mir die ganze Anwedung lagged und block.

    Mache ich stattdessen:

    
    int iterations= TIMEOUT_VALUE/10;
    
    while(! waitEvent.WaitOne(10))
    {
        if(iterations-- <0)
        {
            break; // NOTAUS .. tritt aber nie auf..
         }
    }
    

    läuft es flüssig.. hmm.. ich verstehe das nicht.. macht das einen unterschied ober ne loop hat und "stückchenweiße" warte?

    Oder habe ich generell. nen problem?;)

    Danke Leute



  • WaitOne blockiert bis entweder der Event "gesetzt" wurde oder der timeout zeit "abgelaufen" ist.
    Und wenn das ganze dann im selben thread wie der restliche code (vermutlich auch UI) läuft dann "hängt" die Anwendung.

    Muss es ein Autoevent sein? Je nach dem was deine Applikation mit der Antwort macht bzw. ob die Anwendung wärend der async aufruf läuft noch andere sachen machen soll (z.b. die UI bedienbar halten) wäre eventuell die Verwendung eines "C# events" die bessere wahl.

    Das ganze könnte dann wie folgt aussehen (komplett ungetestet)

    public class CallbackHelper
    {
        public delegate void SampleEventHandler();
    
        public event SampleEventHandler SampleEvent;
    
        void RaiseSampleEvent()
        {
            SampleEvent?.Invoke();
        }
    }
    
    void CAllbackFunc(IntPtr context)
    {
      ( (CallbackHelper)((GCHandle)context).Target)).RaiseSampleEvent();
     }
    
    class Program
    {
        private CallbackHelper callbackHelper = new CallbackHelper();
        
        public Program()
        {
            callbackHelper.SampleEvent += OnCallback;
        }
        
        private void OnCallback()
        {
            ....
        }
        
        public void CallNative()
        {
            GCHandle managedContext = GCHandle.Alloc(callbackHelper);
            MyNativeWrapper.MyFunc((IntPtr)managedContext , _CallbackDelegate,TIMEOUT_VALUE,....);
        }
    }
    

    Wobei in diesem Beispiel vermutlich man nicht mitbekommt wenn der timeout abgelaufen ist.
    Wenn das wichtig ist. Könnte man das mit dem Autoevent in einem separaten thread laufen lassen, welche dann z.b. via einem C# event das ergebnis mitteilt.



  • hmm.. würde ich die ganze funktion einfach in einem neuen Thread wrappen

    Task.Wait(new Task(()=> meinFunc());
    

    wäre es besser, das Callback wird allerdings immer im UI Thread bearbeitet, das macht die API darunter so..


Log in to reply