none
Error beim Benutzen von Async und await RRS feed

  • Frage

  • hallo,

    ich bin noch relativ unerfahren im Programmiere und wollte eine App schreiben die einige Daten für mich verwaltet und abspeichert. Dabei bin ich auf das Problem gestoßen, dass das schreiben von await einen fehler verursacht, bei der Stelle:

    await WriteToFile(n);

    Diese Zeile wird Rot unterringet wenn await da ist und grün wenn es wag ist.

    public void Speichern(double[] n) { Boolean save = true; switch (fachnr) { case 1: mathenoten = n; break; case 2: deutschnoten = n; break; default: save = false; break; } if(save) await WriteToFile(n); } // Speichern public async Task WriteToFile(double[] n) { for (int i = 0; i < n.Length; i++) { // Get the text data from the textbox. byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(n[i].ToString().ToCharArray()); // Get the local folder. StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder; // Create a new folder name DataFolder. var dataFolder = await local.CreateFolderAsync("Fach", CreationCollisionOption.OpenIfExists); // Create a new file named DataFile.txt. var file = await dataFolder.CreateFileAsync(i+".txt", CreationCollisionOption.ReplaceExisting); // Write the data from the textbox. using (var s = await file.OpenStreamForWriteAsync()) { s.Write(fileBytes, 0, fileBytes.Length); } } }

    Ich hoffe jemand kann mir helfen. Danke.

    P.S.: Ich Programmiere in Visual Studio 2013 Community.


    • Bearbeitet ADGS Donnerstag, 4. Juni 2015 18:58
    Donnerstag, 4. Juni 2015 18:53

Antworten

Alle Antworten

  • Hallo,

    await kann immer nur in Methoden verwendet werden die als async deklariert sind. Asynchrone Methoden die mit await benutzt werden sollen müssen entweder Task oder Task<T> zurück geben. Ändere also deine Speichern-Methode ab:

    public async Task Speichern(double[] n){
      await Task.Run(()=>{
        //Dein Code
      });
    }
    
    
    Der Aufruf muss dann entsprechend auch wieder mit await erfolgen. Lediglich Eventhandler müssen nicht zwingend Task zurück geben, sondern können auch void verwenden. Das Problem an anderen Stellen ist, dass eben nicht mehr auf die Ausführung gewartet werden kann.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert ADGS Freitag, 5. Juni 2015 09:17
    Donnerstag, 4. Juni 2015 19:50
    Moderator
  • Danke.

    Jetzt habe ich jedoch das Problem das ich die Methoden für die Buttons auch ändern müsste. Das würde wenn ich es richtig verstanden habe, jetzt so aussehen. Jedoch muss eine Click Methode ja ein void sein. Wie kann ich das lösen?

    private async Task Musik_Click(object sender, RoutedEventArgs e)
            {
                Fach = "Musik";
                fachnr = 5;
                AusFach.Text = Fach;
                await ReadFile(musiknoten);
            }
    
    
            
            public async Task Speichern(double[] n)
            {
                Boolean save = true;
                switch (fachnr)
                {
                    case 1:
                        mathenoten = n;
                        break;
    
                    case 2:
                        deutschnoten = n;                                        
                        break;
    
                    default:
                        save = false;
                        break;
                }
                if(save)
               await WriteToFile(n);
            }
            // Speichern
    
    
            public async Task WriteToFile(double[] n)
            {
                for (int i = 0; i < n.Length; i++)
                {
                    // Get the text data from the textbox. 
                    byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(n[i].ToString().ToCharArray());
    
                    // Get the local folder.
                    StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
    
                    // Create a new folder name DataFolder.
                    var dataFolder = await local.CreateFolderAsync("Fach",
                        CreationCollisionOption.OpenIfExists);
    
                    // Create a new file named DataFile.txt.
                    var file = await dataFolder.CreateFileAsync(i+".txt",
                    CreationCollisionOption.ReplaceExisting);
    
                    // Write the data from the textbox.
                    using (var s = await file.OpenStreamForWriteAsync())
                    {
                        s.Write(fileBytes, 0, fileBytes.Length);
                    }
                }
            }
            // Aufrufen
            public async Task ReadFile(double[] n)
            {
              try
                    {
                for (int i = 0; i < n.Length; i++)
                {
                    
                        // Get the local folder.
                        StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
    
                        if (local != null)
                        {
                            // Get the DataFolder folder.
                            var dataFolder = await local.GetFolderAsync("Fach");
    
                            // Get the file.
                            var file = await dataFolder.OpenStreamForReadAsync(i + ".txt");
    
                            // Read the data.
                            using (StreamReader streamReader = new StreamReader(file))
                            {
                                n[i] = double.Parse(streamReader.ReadToEnd());
                            }
    
                        }
                    }
                    
                }
              catch
              {
                  n = null;
              }
                notenakuell = n;
                intxtein(notenakuell);
            }
    
    
    
    
            // Gespeicherte Arrray in die TextBox einfügen
            public void intxtein(double[] n)
            {
                    Klausur1Note.Text = n[0].ToString();
                    Klausur2Note.Text = n[1].ToString();
                    Kurzarbeit1Note.Text = n[2].ToString();
                    Kurzarbeit2Note.Text = n[3].ToString();
                    EX1Note.Text = n[4].ToString();
                    EX2Note.Text = n[5].ToString();
                    EX3Note.Text = n[6].ToString();
                    Mitarbeit1Note.Text = n[7].ToString();
                    Mitarbeit2Note.Text = n[8].ToString();
                    Mitarbeit3Note.Text = n[9].ToString();
                    Abfrage1Note.Text = n[10].ToString();
                    Abfrage2Note.Text = n[11].ToString();
                }
    
            
            }
        }

    Donnerstag, 4. Juni 2015 21:43
  • Ja, wie ich oben schon schrieb:
    Lediglich Eventhandler müssen nicht zwingend Task zurück geben, sondern können auch void verwenden.
    Du kannst theoretisch überall void nehmen, nur muss dieser Aufruf eben ohne await erfolgen. Das hat dann zur Folge das beim Aufrufen ein 2. Thread angelegt wird. Wenn du also auf den Button klickst läuft die GUI weiter wärend der Code behind in einem anderen Thread arbeitet. Das ist der Grund warum man eigentlich fast überall Task zurück gibt - außer eben bei GUI Interaktionen.

    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort vorgeschlagen Holger M. Rößler Freitag, 5. Juni 2015 05:38
    • Als Antwort markiert ADGS Freitag, 5. Juni 2015 09:18
    Donnerstag, 4. Juni 2015 21:48
    Moderator