Async programlarında kontrol akışı (C#)Control flow in async programs (C#)

Anahtar kelimeleri kullanarak eşzamanlı programları daha kolay async yazabilir await ve sürdürebilirsiniz.You can write and maintain asynchronous programs more easily by using the async and await keywords. Ancak, programınızın nasıl çalıştığını anlamazsanız sonuçlar sizi şaşırtabilir.However, the results might surprise you if you don't understand how your program operates. Bu konu, denetimin bir yöntemden diğerine ne zaman taşındığını ve her seferinde hangi bilgilerin aktarıldığını göstermek için basit bir async programı aracılığıyla denetim akışını izler.This topic traces the flow of control through a simple async program to show you when control moves from one method to another and what information is transferred each time.

Genel olarak, async (C#) değiştirici ile asynchronous kodu içeren yöntemleri işaretlersiniz.In general, you mark methods that contain asynchronous code with the async (C#) modifier. Async değiştirici ile işaretlenmiş bir yöntemde, yöntemin tamamlanmasını beklemek için nerede duraklatılır söyleniyor belirtmek için bir bekleme (C#) işleci kullanabilirsiniz.In a method that's marked with an async modifier, you can use an await (C#) operator to specify where the method pauses to wait for a called asynchronous process to complete. Daha fazla bilgi için, async ile Asynchronous Programming bakın ve bekliyor (C#).For more information, see Asynchronous Programming with async and await (C#).

Aşağıdaki örnek, belirli bir web sitesinin içeriğini dize olarak indirmek ve dize uzunluğunu görüntülemek için async yöntemlerini kullanır.The following example uses async methods to download the contents of a specified website as a string and to display the length of the string. Örnek, aşağıdaki iki yöntemi içerir.The example contains the following two methods.

  • startButton_Click, sonucu AccessTheWebAsync arar ve görüntüler.startButton_Click, which calls AccessTheWebAsync and displays the result.

  • AccessTheWebAsync, bir web sitesinin içeriğini dize olarak indirir ve dize uzunluğunu döndürür.AccessTheWebAsync, which downloads the contents of a website as a string and returns the length of the string. AccessTheWebAsynciçeriğini indirmek için HttpClient bir GetStringAsync(String)eşzamanlı yöntem kullanır.AccessTheWebAsync uses an asynchronous HttpClient method, GetStringAsync(String), to download the contents.

Program boyunca stratejik noktalarda numaralanmış ekran çizgileri görünür ve programın nasıl çalıştığını anlamanıza ve işaretlenen her noktada neler olduğunu açıklamanıza yardımcı olur.Numbered display lines appear at strategic points throughout the program to help you understand how the program runs and to explain what happens at each point that is marked. Ekran çizgileri "Bİr" ile "ALTI" arasında etiketlenir.The display lines are labeled "ONE" through "SIX." Etiketler, programın bu kod satırlarına ulaşma sırasını temsil ediyor.The labels represent the order in which the program reaches these lines of code.

Aşağıdaki kod, programın anahatlarını gösterir.The following code shows an outline of the program.

public partial class MainWindow : Window
{
    // . . .
    private async void startButton_Click(object sender, RoutedEventArgs e)
    {
        // ONE
        Task<int> getLengthTask = AccessTheWebAsync();

        // FOUR
        int contentLength = await getLengthTask;

        // SIX
        resultsTextBox.Text +=
            $"\r\nLength of the downloaded string: {contentLength}.\r\n";
    }

    async Task<int> AccessTheWebAsync()
    {
        // TWO
        HttpClient client = new HttpClient();
        Task<string> getStringTask =
            client.GetStringAsync("https://msdn.microsoft.com");

        // THREE
        string urlContents = await getStringTask;

        // FIVE
        return urlContents.Length;
    }
}

Etiketli konumların her biri, "BİR" ile "ALTI" arasında, programın geçerli durumu hakkında bilgi görüntüler.Each of the labeled locations, "ONE" through "SIX," displays information about the current state of the program. Aşağıdaki çıktı üretilir:The following output is produced:

ONE:   Entering startButton_Click.
           Calling AccessTheWebAsync.

TWO:   Entering AccessTheWebAsync.
           Calling HttpClient.GetStringAsync.

THREE: Back in AccessTheWebAsync.
           Task getStringTask is started.
           About to await getStringTask & return a Task<int> to startButton_Click.

FOUR:  Back in startButton_Click.
           Task getLengthTask is started.
           About to await getLengthTask -- no caller to return to.

FIVE:  Back in AccessTheWebAsync.
           Task getStringTask is complete.
           Processing the return statement.
           Exiting from AccessTheWebAsync.

SIX:   Back in startButton_Click.
           Task getLengthTask is finished.
           Result from AccessTheWebAsync is stored in contentLength.
           About to display contentLength and exit.

Length of the downloaded string: 33946.

Programı ayarlamaSet up the program

Bu konunun kullandığı kodu MSDN'den indirebilir veya kendiniz oluşturabilirsiniz.You can download the code that this topic uses from MSDN, or you can build it yourself.

Not

Örneği çalıştırmak için Visual Studio 2012 veya daha yeni ve .NET Framework 4.5 veya daha yeni bilgisayarınıza yüklü olması gerekir.To run the example, you must have Visual Studio 2012 or newer and the .NET Framework 4.5 or newer installed on your computer.

Programı indirinDownload the program

Bu konu yla ilgili uygulamayı Async Sample: Control Flow in Async Programs'danindirebilirsiniz.You can download the application for this topic from Async Sample: Control Flow in Async Programs. Aşağıdaki adımlar programı açın ve çalıştırın.The following steps open and run the program.

  1. İndirilen dosyanın zip'ini açın ve Ardından Visual Studio'yu başlatın.Unzip the downloaded file, and then start Visual Studio.

  2. Menü çubuğunda Dosya > > Projesi/Çözümü'nüseçin.On the menu bar, choose File > Open > Project/Solution.

  3. Sıkıştırılmamış örnek kodu tutan klasöre gidin, çözüm (.sln) dosyasını açın ve ardından projeyi oluşturmak ve çalıştırmak için F5 tuşunu seçin.Navigate to the folder that holds the unzipped sample code, open the solution (.sln) file, and then choose the F5 key to build and run the project.

Programı Kendiniz oluşturunCreate the program Yourself

Aşağıdaki Windows Sunu Temeli (WPF) projesi, bu konu için kod örneğini içerir.The following Windows Presentation Foundation (WPF) project contains the code example for this topic.

Projeyi çalıştırmak için aşağıdaki adımları gerçekleştirin:To run the project, perform the following steps:

  1. Visual Studio’yu çalıştırın.Start Visual Studio.

  2. Menü çubuğundaYeni > Proje yi seçin. > On the menu bar, choose File > New > Project.

    Yeni Proje iletişim kutusu açılır.The New Project dialog box opens.

  3. Yüklü > Görsel C# > Windows Masaüstü kategorisini seçin ve ardından proje şablonları listesinden WPF Uygulamasını seçin.Choose the Installed > Visual C# > Windows Desktop category, and then choose WPF App from the list of project templates.

  4. Projenin AsyncTracer adı olarak girin ve sonra Tamam düğmesini seçin.Enter AsyncTracer as the name of the project, and then choose the OK button.

    Yeni proje Çözüm Gezgini'ndegörünür.The new project appears in Solution Explorer.

  5. Visual Studio Code Editor'da MainWindow.xaml sekmesini seçin.In the Visual Studio Code Editor, choose the MainWindow.xaml tab.

    Sekme görünmüyorsa, Solution Explorer'daMainWindow.xaml için kısayol menüsünü açın ve ardından Kodu Görüntüle'yiseçin.If the tab isn’t visible, open the shortcut menu for MainWindow.xaml in Solution Explorer, and then choose View Code.

  6. MainWindow.xaml'ın XAML görünümünde kodu aşağıdaki kodla değiştirin.In the XAML view of MainWindow.xaml, replace the code with the following code.

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="AsyncTracer.MainWindow"
            Title="Control Flow Trace" Height="350" Width="592">
        <Grid>
            <Button x:Name="startButton" Content="Start
    " HorizontalAlignment="Left" Margin="250,10,0,0" VerticalAlignment="Top" Width="75" Height="24"  Click="startButton_Click" d:LayoutOverrides="GridBox"/>
            <TextBox x:Name="resultsTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="576" Height="265" FontFamily="Lucida Console" FontSize="10" VerticalScrollBarVisibility="Visible" Grid.ColumnSpan="3"/>
        </Grid>
    </Window>
    

    MainWindow.xaml'ın Tasarım görünümünde metin kutusu ve düğme içeren basit bir pencere görüntülenir.A simple window that contains a text box and a button appears in the Design view of MainWindow.xaml.

  7. Için System.Net.Httpbir başvuru ekleyin.Add a reference for System.Net.Http.

  8. Çözüm Gezgini'nde, MainWindow.xaml.cs için kısayol menüsünü açın ve ardından Kodu Görüntüle'yiseçin.In Solution Explorer, open the shortcut menu for MainWindow.xaml.cs, and then choose View Code.

  9. MainWindow.xaml.cs kodu aşağıdaki kodla değiştirin.In MainWindow.xaml.cs, replace the code with the following code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    // Add a using directive and a reference for System.Net.Http;
    using System.Net.Http;
    
    namespace AsyncTracer
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private async void startButton_Click(object sender, RoutedEventArgs e)
            {
                // The display lines in the example lead you through the control shifts.
                resultsTextBox.Text += "ONE:   Entering startButton_Click.\r\n" +
                    "           Calling AccessTheWebAsync.\r\n";
    
                Task<int> getLengthTask = AccessTheWebAsync();
    
                resultsTextBox.Text += "\r\nFOUR:  Back in startButton_Click.\r\n" +
                    "           Task getLengthTask is started.\r\n" +
                    "           About to await getLengthTask -- no caller to return to.\r\n";
    
                int contentLength = await getLengthTask;
    
                resultsTextBox.Text += "\r\nSIX:   Back in startButton_Click.\r\n" +
                    "           Task getLengthTask is finished.\r\n" +
                    "           Result from AccessTheWebAsync is stored in contentLength.\r\n" +
                    "           About to display contentLength and exit.\r\n";
    
                resultsTextBox.Text +=
                    $"\r\nLength of the downloaded string: {contentLength}.\r\n";
            }
    
            async Task<int> AccessTheWebAsync()
            {
                resultsTextBox.Text += "\r\nTWO:   Entering AccessTheWebAsync.";
    
                // Declare an HttpClient object.
                HttpClient client = new HttpClient();
    
                resultsTextBox.Text += "\r\n           Calling HttpClient.GetStringAsync.\r\n";
    
                // GetStringAsync returns a Task<string>.
                Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");
    
                resultsTextBox.Text += "\r\nTHREE: Back in AccessTheWebAsync.\r\n" +
                    "           Task getStringTask is started.";
    
                // AccessTheWebAsync can continue to work until getStringTask is awaited.
    
                resultsTextBox.Text +=
                    "\r\n           About to await getStringTask and return a Task<int> to startButton_Click.\r\n";
    
                // Retrieve the website contents when task is complete.
                string urlContents = await getStringTask;
    
                resultsTextBox.Text += "\r\nFIVE:  Back in AccessTheWebAsync." +
                    "\r\n           Task getStringTask is complete." +
                    "\r\n           Processing the return statement." +
                    "\r\n           Exiting from AccessTheWebAsync.\r\n";
    
                return urlContents.Length;
            }
        }
    }
    
  10. Programı çalıştırmak için F5 tuşunu seçin ve ardından Başlat düğmesini seçin.Choose the F5 key to run the program, and then choose the Start button.

    Şu çıktı görünür:The following output appears:

    ONE:   Entering startButton_Click.
               Calling AccessTheWebAsync.
    
    TWO:   Entering AccessTheWebAsync.
               Calling HttpClient.GetStringAsync.
    
    THREE: Back in AccessTheWebAsync.
               Task getStringTask is started.
               About to await getStringTask & return a Task<int> to startButton_Click.
    
    FOUR:  Back in startButton_Click.
               Task getLengthTask is started.
               About to await getLengthTask -- no caller to return to.
    
    FIVE:  Back in AccessTheWebAsync.
               Task getStringTask is complete.
               Processing the return statement.
               Exiting from AccessTheWebAsync.
    
    SIX:   Back in startButton_Click.
               Task getLengthTask is finished.
               Result from AccessTheWebAsync is stored in contentLength.
               About to display contentLength and exit.
    
    Length of the downloaded string: 33946.
    

Programı izlemeTrace the program

Bir ve İkİ AdımSteps ONE and TWO

İlk iki görüntü satırı yolu startButton_Click AccessTheWebAsyncçağrı AccessTheWebAsync olarak izler ve HttpClient eşsenkronize yöntemi GetStringAsync(String)çağırır.The first two display lines trace the path as startButton_Click calls AccessTheWebAsync, and AccessTheWebAsync calls the asynchronous HttpClient method GetStringAsync(String). Aşağıdaki resimde yöntemden yönteme çağrılar özetleniyor.The following image outlines the calls from method to method.

Bir ve İkİ AdımSteps ONE and TWO

Her ikisinin AccessTheWebAsync de client.GetStringAsync Task<TResult>dönüş türü ve .The return type of both AccessTheWebAsync and client.GetStringAsync is Task<TResult>. Için AccessTheWebAsync, TResult bir sayıdır.For AccessTheWebAsync, TResult is an integer. Için GetStringAsync, TResult bir dizedir.For GetStringAsync, TResult is a string. Async yöntemi iade türleri hakkında daha fazla bilgi için, Bkz. Async Return Types (C#).For more information about async method return types, see Async Return Types (C#).

Görev döndüren async yöntemi, denetim arayana geri kaydığında bir görev örneği döndürür.A task-returning async method returns a task instance when control shifts back to the caller. Denetim, çağrılan yöntemde bir await işleçle karşılaşıldığında veya çağrılan yöntem sona erdiğinde async yönteminden arayana geri döner.Control returns from an async method to its caller either when an await operator is encountered in the called method or when the called method ends. "ALTI" ile "ÜÇ" etiketli ekran çizgileri işlemin bu bölümünü izler.The display lines that are labeled "THREE" through "SIX" trace this part of the process.

Üçüncü AdımStep THREE

, AccessTheWebAsyncasynchronous yöntemi GetStringAsync(String) hedef web sayfasının içeriğini indirmek için denir.In AccessTheWebAsync, the asynchronous method GetStringAsync(String) is called to download the contents of the target webpage. Denetim döndüğünden AccessTheWebAsync client.GetStringAsync ne zaman ait sayılsın. client.GetStringAsyncControl returns from client.GetStringAsync to AccessTheWebAsync when client.GetStringAsync returns.

Yöntem, client.GetStringAsync getStringTask AccessTheWebAsync'deki değişkene atanan dize görevini döndürürThe client.GetStringAsync method returns a task of string that’s assigned to the getStringTask variable in AccessTheWebAsync. Örnek programdaki aşağıdaki satır, atamaya yapılan çağrıyı client.GetStringAsync ve atamayı gösterir.The following line in the example program shows the call to client.GetStringAsync and the assignment.

Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");

Görevi, sonunda gerçek bir dize üreterek client.GetStringAsync bir söz olarak düşünebilirsiniz.You can think of the task as a promise by client.GetStringAsync to produce an actual string eventually. Bu arada, AccessTheWebAsync bu iş varsa bu söz dize bağlı client.GetStringAsyncdeğildir , bu client.GetStringAsync iş beklerken devam edebilirsiniz.In the meantime, if AccessTheWebAsync has work to do that doesn't depend on the promised string from client.GetStringAsync, that work can continue while client.GetStringAsync waits. Örnekte, "ÜÇ" olarak etiketlenen aşağıdaki çıktı satırları, bağımsız çalışma yapma fırsatını temsilIn the example, the following lines of output, which are labeled "THREE," represent the opportunity to do independent work

THREE: Back in AccessTheWebAsync.
           Task getStringTask is started.
           About to await getStringTask & return a Task<int> to startButton_Click.

Aşağıdaki ifade, beklenen AccessTheWebAsync zaman getStringTask ilerlemeyi askıya adatır.The following statement suspends progress in AccessTheWebAsync when getStringTask is awaited.

string urlContents = await getStringTask;

Aşağıdaki resimde, bir bekleme client.GetStringAsync işlecinin getStringTask getStringTask uygulanmasına ve oluşturulmasına kadar denetim akışı gösterilmektedir.The following image shows the flow of control from client.GetStringAsync to the assignment to getStringTask and from the creation of getStringTask to the application of an await operator.

Üçüncü AdımStep THREE

Bekleyen ifade dönene client.GetStringAsync kadar askıya alınır. AccessTheWebAsyncThe await expression suspends AccessTheWebAsync until client.GetStringAsync returns. Bu arada, kontrol arayan döner AccessTheWebAsync startButton_Click, .In the meantime, control returns to the caller of AccessTheWebAsync, startButton_Click.

Not

Genellikle, hemen bir eşzamanlı yöntem için çağrı bekliyor.Typically, you await the call to an asynchronous method immediately. Örneğin, aşağıdaki atama oluşturan önceki kodu değiştirebilir ve sonra getStringTaskbekliyor:string urlContents = await client.GetStringAsync("https://msdn.microsoft.com");For example, the following assignment could replace the previous code that creates and then awaits getStringTask: string urlContents = await client.GetStringAsync("https://msdn.microsoft.com");

Bu konuda, program aracılığıyla denetim akışını işaretleyen çıkış hatlarını karşılamak için bekleme işleci daha sonra uygulanır.In this topic, the await operator is applied later to accommodate the output lines that mark the flow of control through the program.

Dördüncü AdımStep FOUR

Beyan edilen dönüş AccessTheWebAsync Task<int>türü.The declared return type of AccessTheWebAsync is Task<int>. Bu nedenle, askıya alındığınızda, AccessTheWebAsync tamsayı görevini startButton_Clickdöndürür.Therefore, when AccessTheWebAsync is suspended, it returns a task of integer to startButton_Click. Döndürülen görevin getStringTask.You should understand that the returned task isn’t getStringTask. Döndürülen görev, askıya alınan yöntemde yapılması gerekenleri temsil eden yeni AccessTheWebAsyncbir tamsayı görevidir.The returned task is a new task of integer that represents what remains to be done in the suspended method, AccessTheWebAsync. Görev tamamlandığında bir AccessTheWebAsync tamsayı üretmek için bir sözdür.The task is a promise from AccessTheWebAsync to produce an integer when the task is complete.

Aşağıdaki deyim, bu görevi getLengthTask değişkene atar.The following statement assigns this task to the getLengthTask variable.

Task<int> getLengthTask = AccessTheWebAsync();

Olduğu AccessTheWebAsyncgibi startButton_Click , görev beklenene kadar eşzamanlı görevin sonuçlarına bağlıgetLengthTaskolmayan çalışmalara devam edebilir .As in AccessTheWebAsync, startButton_Click can continue with work that doesn’t depend on the results of the asynchronous task (getLengthTask) until the task is awaited. Aşağıdaki çıktı satırları bu çalışmayı temsil ediyor.The following output lines represent that work.

FOUR:  Back in startButton_Click.
           Task getLengthTask is started.
           About to await getLengthTask -- no caller to return to.

Beklenen startButton_Click ilerleme getLengthTask askıya alınır.Progress in startButton_Click is suspended when getLengthTask is awaited. Aşağıdaki atama deyimi startButton_Click tamamlanana kadar AccessTheWebAsync askıya alınır.The following assignment statement suspends startButton_Click until AccessTheWebAsync is complete.

int contentLength = await getLengthTask;

Aşağıdaki resimde, oklar bekleme ifadesinden bir değerin AccessTheWebAsync atanmasına getLengthTaskkadar denetim akışını gösterir , startButton_Click beklenene kadar getLengthTask normal işleme takip eder.In the following illustration, the arrows show the flow of control from the await expression in AccessTheWebAsync to the assignment of a value to getLengthTask, followed by normal processing in startButton_Click until getLengthTask is awaited.

Dördüncü AdımStep FOUR

Adım BEŞStep FIVE

client.GetStringAsync Sinyaller tamamlandığında, işlem AccessTheWebAsync askıya alındı ve bekleme deyimini geçmeye devam edebilir.When client.GetStringAsync signals that it’s complete, processing in AccessTheWebAsync is released from suspension and can continue past the await statement. Aşağıdaki çıktı satırları işlemin yeniden başlamasını temsil emzdir.The following lines of output represent the resumption of processing.

FIVE:  Back in AccessTheWebAsync.
           Task getStringTask is complete.
           Processing the return statement.
           Exiting from AccessTheWebAsync.

İade deyiminin operand'ı, urlContents.Lengthdöndüren AccessTheWebAsync görevde depolanır.The operand of the return statement, urlContents.Length, is stored in the task that AccessTheWebAsync returns. Bekleyen ifade bu değeri getLengthTask 'den startButton_Clickalır.The await expression retrieves that value from getLengthTask in startButton_Click.

Aşağıdaki resim, (ve) client.GetStringAsync getStringTasktamamlandıktan sonra denetim aktarımını gösterir.The following image shows the transfer of control after client.GetStringAsync (and getStringTask) are complete.

Adım BEŞStep FIVE

AccessTheWebAsynctamamlanmasını sağlar ve denetim startButton_Clicktamamlanmayı bekleyen e dönüşlere döner.AccessTheWebAsync runs to completion, and control returns to startButton_Click, which is awaiting the completion.

Altıncı AdımStep SIX

AccessTheWebAsync Tamamlandığında, işleme bekleme deyimini startButton_Async'de geçmiş olarak devam edebilir.When AccessTheWebAsync signals that it’s complete, processing can continue past the await statement in startButton_Async. Aslında, programın yapacak başka bir şeyi yok.In fact, the program has nothing more to do.

Aşağıdaki çıktı satırları aşağıdaki işlemin startButton_Asyncdevamını temsil eden:The following lines of output represent the resumption of processing in startButton_Async:

SIX:   Back in startButton_Click.
           Task getLengthTask is finished.
           Result from AccessTheWebAsync is stored in contentLength.
           About to display contentLength and exit.

Bekleyen ifade, getLengthTask AccessTheWebAsync'deki iade deyiminin operand'ı olan sonda değerinden alır.The await expression retrieves from getLengthTask the integer value that’s the operand of the return statement in AccessTheWebAsync. Aşağıdaki deyim, bu değeri contentLength değişkene atar.The following statement assigns that value to the contentLength variable.

int contentLength = await getLengthTask;

Aşağıdaki resimde denetimin 'den AccessTheWebAsync startButton_Click'e geri dönüşü gösterilmektedirThe following image shows the return of control from AccessTheWebAsync to startButton_Click.

Altıncı AdımStep SIX

Ayrıca bkz.See also