How do I wait until Task is finished in C#?

后端 未结 6 871
孤街浪徒
孤街浪徒 2020-12-04 23:49

I want to send a request to a server and process the returned value:

private static string Send(int id)
{
    Task responseTask =          


        
相关标签:
6条回答
  • 2020-12-05 00:26

    A clean example that answers the Title

    string output = "Error";
    Task task = Task.Factory.StartNew(() =>
    {
        System.Threading.Thread.Sleep(2000);
        output = "Complete";
    });
    
    task.Wait();
    Console.WriteLine(output);
    
    0 讨论(0)
  • 2020-12-05 00:38

    I'm an async novice, so I can't tell you definitively what is happening here. I suspect that there's a mismatch in the method execution expectations, even though you are using tasks internally in the methods. I think you'd get the results you are expecting if you changed Print to return a Task<string>:

    private static string Send(int id)
    {
        Task<HttpResponseMessage> responseTask = client.GetAsync("aaaaa");
        Task<string> result;
        responseTask.ContinueWith(x => result = Print(x));
        result.Wait();
        responseTask.Wait(); // There's likely a better way to wait for both tasks without doing it in this awkward, consecutive way.
        return result.Result;
    }
    
    private static Task<string> Print(Task<HttpResponseMessage> httpTask)
    {
        Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
        string result = string.Empty;
        task.ContinueWith(t =>
        {
            Console.WriteLine("Result: " + t.Result);
            result = t.Result;
        });
        return task;
    }
    
    0 讨论(0)
  • 2020-12-05 00:39

    When working with continuations I find it useful to think of the place where I write .ContinueWith as the place from which execution immediately continues to the statements following it, not the statements 'inside' it. In that case it becomes clear that you would get an empty string returned in Send. If your only processing of the response is writing it to the console, you don't need any Wait in Ito's solution - the console printout will happen without waits but both Send and Print should return void in that case. Run this in console app and you will get printout of the page.

    IMO, waits and Task.Result calls (which block) are necessary sometimes, depending on your desired flow of control, but more often they are a sign that you don't really use asynchronous functionality correctly.

    namespace TaskTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Send();
                Console.WriteLine("Press Enter to exit");
                Console.ReadLine();
            }
    
            private static void Send()
            {
                HttpClient client = new HttpClient();
                Task<HttpResponseMessage> responseTask = client.GetAsync("http://google.com");
                responseTask.ContinueWith(x => Print(x));
            }
    
            private static void Print(Task<HttpResponseMessage> httpTask)
            {
                Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
                Task continuation = task.ContinueWith(t =>
                {
                    Console.WriteLine("Result: " + t.Result);
                });
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 00:42

    It waits for client.GetAsync("aaaaa");, but doesn't wait for result = Print(x)

    Try responseTask.ContinueWith(x => result = Print(x)).Wait()

    --EDIT--

    Task responseTask = Task.Run(() => { 
        Thread.Sleep(1000); 
        Console.WriteLine("In task"); 
    });
    responseTask.ContinueWith(t=>Console.WriteLine("In ContinueWith"));
    responseTask.Wait();
    Console.WriteLine("End");
    

    Above code doesn't guarantee the output:

    In task
    In ContinueWith
    End
    

    But this does (see the newTask)

    Task responseTask = Task.Run(() => { 
        Thread.Sleep(1000); 
        Console.WriteLine("In task"); 
    });
    Task newTask = responseTask.ContinueWith(t=>Console.WriteLine("In ContinueWith"));
    newTask.Wait();
    Console.WriteLine("End");
    
    0 讨论(0)
  • 2020-12-05 00:45
    async Task<int> AccessTheWebAsync()  
    {   
        // You need to add a reference to System.Net.Http to declare client.  
        HttpClient client = new HttpClient();  
    
        // GetStringAsync returns a Task<string>. That means that when you await the  
        // task you'll get a string (urlContents).  
        Task<string> getStringTask = 
    
        client.GetStringAsync("http://msdn.microsoft.com");  
    
        // You can do work here that doesn't rely on the string from GetStringAsync.  
        DoIndependentWork();  
    
        // The await operator suspends AccessTheWebAsync.  
        //  - AccessTheWebAsync can't continue until getStringTask is complete.  
        //  - Meanwhile, control returns to the caller of AccessTheWebAsync.  
        //  - Control resumes here when getStringTask is complete.   
        //  - The await operator then retrieves the string result from 
        getStringTask.  
        string urlContents = await getStringTask;  
    
        // The return statement specifies an integer result.  
        // Any methods that are awaiting AccessTheWebenter code hereAsync retrieve the length 
        value.  
        return urlContents.Length;  
    }  
    
    0 讨论(0)
  • 2020-12-05 00:50

    Your Print method likely needs to wait for the continuation to finish (ContinueWith returns a task which you can wait on). Otherwise the second ReadAsStringAsync finishes, the method returns (before result is assigned in the continuation). Same problem exists in your send method. Both need to wait on the continuation to consistently get the results you want. Similar to below

    private static string Send(int id)
    {
        Task<HttpResponseMessage> responseTask = client.GetAsync("aaaaa");
        string result = string.Empty;
        Task continuation = responseTask.ContinueWith(x => result = Print(x));
        continuation.Wait();
        return result;
    }
    
    private static string Print(Task<HttpResponseMessage> httpTask)
    {
        Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
        string result = string.Empty;
        Task continuation = task.ContinueWith(t =>
        {
            Console.WriteLine("Result: " + t.Result);
            result = t.Result;
        });
        continuation.Wait();  
        return result;
    }
    
    0 讨论(0)
提交回复
热议问题