简体   繁体   中英

How can I wait for the asynchronous method result before execute the rest of the main thread?

I would like to download a file with asynchronous method, in order to show the actual progress of the download to the user.

using System;
using System.Net;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        public static void downloadFile(string url)
        {
            Object LockObject = new Object();

            using (var client = new WebClient())
            {
                int left = Console.CursorLeft;
                int top = Console.CursorTop;

                client.DownloadProgressChanged += (o, e) =>
                {
                    lock (LockObject)
                    {

                        Console.SetCursorPosition(0, 0);
                        Console.Write(e.ProgressPercentage + "%");

                    }
                };

                client.DownloadFileAsync(new Uri(url), @"c:\asd");
            }
        }
        static void Main(string[] args)
        {
            Task task = Task.Factory.StartNew(() => downloadFile("http://download.lsoft.net/ActiveDataStudioSetup.exe"));
            task.Wait();

            //There can be lots of funcs after download......
            //!!!
            Console.WriteLine("\nIt should be seen ONLY after the full download"); 

            Console.ReadKey();

        }
    }
}

The download procedure seems to be fine, file is getting and I also see the actual state of that, but after the method called, everything will be executed right after the calling, but the main thread should wait the complete of the download first.

The problem is that your downloadFile method is an asynchronous void method. The method just starts an asynchronous operation and returns immediately, but it doesn't provide any way to inform the caller when it has completed. That you start the asynchronous operation in another thread and then wait for it to finish starting the asynchronous operation in your main method before continuing doesn't result in it waiting for it to complete the download, as you're seeing.

You need to alter your download file so that it returns a Task that indicates when it's finished:

public static Task DownloadFile(string url)
{
    using (var client = new WebClient())
    {
        client.DownloadProgressChanged += (o, e) =>
        {
            lock (client)
            {
                Console.SetCursorPosition(0, 0);
                Console.Write(e.ProgressPercentage + "%");
            }
        };
        return client.DownloadFileTaskAsync(new Uri(url), @"c:\asd");
    }
}

Then of course there's no reason at all to start it from another thread. You just call the method to start the download:

private static void Main()
{
    Task task = DownloadFile("http://download.lsoft.net/ActiveDataStudioSetup.exe");
    task.Wait();

    Console.WriteLine("\nIt should be seen ONLY after the full download");

    Console.WriteLine();
    Console.WriteLine("Press any key to Exit. . . ");
    Console.ReadKey(true);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM