none
await async Task

    Frage

  • Hi,
    folgendes.
    Ich habe eine Hauptfunktion die arbeitet die Schritte ab, passt.
    Eine andere benötigt Zeit, UserInterface soll nicht 'hängen' also Task, await, async
    Innerhalb der Funktion CallImportProgram verhält es sich wie synchron.
       
    Problem:
      In der Hauptfunktion,
        wird alles sofort ausgeführt.

    Fragen:
      Was müßte ich machen, damit bei CallImportProgram gewartet wird.
      Müßte ich da den Event ins Spiel bringen?

        protected AutoResetEvent EvImport;
      if (!EvImport.WaitOne(50000))
        EvImport.Set();   
             
    Vielen Dank für Tipps.
    Gruß, Markus
    //Methode Haupt
    
    ToDo1();
    ToDo2();
    
    try
    {
       CallImportProgram(path);
       // await CallImportProgram(path); so funktioniert es nicht, 
    }
    catch (Exception ex)
    {
    	ShowMessageBox("01", "ERROR");
    return;
    }
    
    ToTo3();
    
    
    
    // --------------------
    protected async void CallImportProgram(string path)
    {
    	try
    	{
    		Process.Start("notepad.exe", "C:\\NewLog1.txt");
    		System.Threading.Thread.Sleep(200);
    
    		CurrentProductionOrder = new ProductionOrder();
    
    		// ** Check is the file created from extern
    		byte[] pData = await CurrentProductionOrder.ReadDataAsync(path, Timeout);
    
    		
    // --------------------
    // Daten async einlesen...
    public async Task<byte[]> ReadDataAsync(string pDatei, int pTimeOutMs)
    {
    
    	while (!File.Exists(pDatei))
    	{

    Samstag, 13. Januar 2018 12:42

Antworten

  • Hi Markus,
    ich habe meinen vorherigen Beitrag gelöscht, da er nicht zu Deiner Frage passt.

    Hier mal eine Demo, wie man das machen kann:

          AutoResetEvent are = new AutoResetEvent(false);
          int Timeout = 5000;
    
          internal void Execute()
          {
            ToDo1();
            ToDo2();
            WaitHandle wh =  are;
            Task.Run(() => CallImportProgram());
            wh.WaitOne(Timeout);
            ToDo3();
          }
    
          void ToDo1() { }
          void ToDo2() { }
          void ToDo3() { }
    
          void CallImportProgram()
          {
            Thread.Sleep(6000); // Arbeit
            are.Set(); // signalisieren, dass fertig
          }

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    Montag, 15. Januar 2018 18:44

Alle Antworten

  • Hi Markus,
    Deine Frage ist etwas unklar. Mit await wartest Du auf das Ende einer asynchronen Methode. Mit diesem Warten wird jedoch die Methode, in welcher await ausgeführt wird, blockiert. Das await hat lediglich den Vorteil, dass andere asynchrone Ereignisse im gleichen Thread abgearbeitet werden können, solange mit await gewartet wird und die anderen aufgerufenen asynchronen Methoden den Thread nicht blockieren.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Samstag, 13. Januar 2018 14:38
  • Hi Peter,

    ich möchte eigentlich, dass auch bei CallImportProgram gewartet wird.

    Wie müßte ich das dann schreiben? Ich will es praktisch weiterreichen. Vielleicht geht das auch nicht, was eben die Frage wäre.

    Viele Grüße Markus

    ToDo1();
    ToDo2();
       CallImportProgram(path);
       // await CallImportProgram(path); so funktioniert es nicht 
    ToTo3()
    Sonntag, 14. Januar 2018 10:51
  • Hi Markus,
    eine einfache Möglichkeit besteht darin, einen zweiten Thread zu starten, in welchem asynchron zum ersten Thread die Arbeiten ausgeführt. Dabei ist lediglich die Frage zu klären, was passieren soll, wenn der zweite Thread seine Arbeit beendet hat. Üblicherweise wird da ein Ereignis ausgelöst, welches der erste Thread nutzen kann, um z.B. eine Anzeige in der Oberfläche zu aktualisieren. Für den Start eines zweiten Threads gibt es je nach Projekttyp unterschiedliche Möglichkeiten.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 14. Januar 2018 10:58
  •  Für den Start eines zweiten Threads gibt es je nach Projekttyp unterschiedliche Möglichkeiten.

    Hi Peter,

    könntest mir das bitte Code mäßig zeigen, wie Du das meinst? Also dann ohne await etc.?

    Grüße, Markus

    Sonntag, 14. Januar 2018 11:39
  • Und für welchen Projekttyp?


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 14. Januar 2018 12:21
  • Hi Peter,

    // --------------------
    protected async void CallImportProgram(string path)
    {
    	try
    	{
    		CurrentProductionOrder = new ProductionOrder();
    
    		byte[] pData = await CurrentProductionOrder.ReadDataAsync(path, Timeout);   // !!!!! hier geht es, wird gewartet
    
    		
    // --------------------
    // Daten async einlesen...
    public async Task<byte[]> ReadDataAsync(string pDatei, int pTimeOutMs)
    {
    
    	while (!File.Exists(pDatei))
    	{

    die Idee ist, dass meine Applikation ein externes Programm aufrufen muss.

    Diese Programm erzeugt eine Textdatei, die ich zu analysieren habe.

    Meine Schrittkette darf nur weitergehen, wenn diese Datei analysiert ist. Das wäre das Ziel. Mein Ansatz war dann es mit await zu tun. Vom Prinzip geht das auch, nur kann ich das nicht weiterreichen.

    Gruß, Markus

    Sonntag, 14. Januar 2018 14:56
  • Hi Markus,
    aus Deinen Codeschnipseln kann ich leider nicht erkennen, was für ein Problem Du hast.

    Du kannst Task.Run nutzen, damit Deine Methode in einem separaten Thread ausgeführt wird, z.B.:

            Task.Run(() => CallImportProgram(path));

    Dann bleibt die Oberfläche bedienbar.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 14. Januar 2018 16:41
  • Hi Peter,
    letztendlich soll lediglich im Hauptzweig gewartet werden bis die Importdatei analysiert ist,
    ohne dass das UserInterface einfriert.

    Müsste ich dann noch den Event ins Spiel bringen.
    Der untere Code tut, bestimmt geht es eleganter.

    Dein Beispiel schaue ich mir an. Danke.

    ToDo1();

    ToDo2();

       CallImportProgram(path);

    ToTo3()

    ToDo3 darf erst bearbeitet werden, wenn CallImportProgram seine Aufgaben erledigt hat.

    CallImportProgram bekommt dafür 5000ms Zeit.

    try
    {
     System.Threading.Tasks.Task.Run(() => CallImportProgram(nameOfFile));
     Stopwatch timeForRead = new Stopwatch();
     timeForRead.Start();
     if (!EvImport.WaitOne(5000))
     {
     }
     if (timeForRead.ElapsedMilliseconds > 4500)
      throw new Exception($"Die Datei für den Auftrag '{Current}' wurde nicht importiert.");
    }
    catch (Exception ex)
    {
     MessageBox("Keine Date gefunden!");
     return;
    }
    Gruß, Markus
    Montag, 15. Januar 2018 17:38
  • Hi Markus,
    ich habe meinen vorherigen Beitrag gelöscht, da er nicht zu Deiner Frage passt.

    Hier mal eine Demo, wie man das machen kann:

          AutoResetEvent are = new AutoResetEvent(false);
          int Timeout = 5000;
    
          internal void Execute()
          {
            ToDo1();
            ToDo2();
            WaitHandle wh =  are;
            Task.Run(() => CallImportProgram());
            wh.WaitOne(Timeout);
            ToDo3();
          }
    
          void ToDo1() { }
          void ToDo2() { }
          void ToDo3() { }
    
          void CallImportProgram()
          {
            Thread.Sleep(6000); // Arbeit
            are.Set(); // signalisieren, dass fertig
          }

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    Montag, 15. Januar 2018 18:44