c#tasks async / await或ContinueWith还是?

时间:2015-04-27 19:20:52

标签: c# async-await task

我从main调用了2个相同的任务(比如这个

static void Main()
    {
        Downloads test = new Downloads();
        test.DisplayResultAsync();
        test.DisplayResultAsync();
        Console.WriteLine("main");
        Console.ReadLine();
    }

),其中DisplayResultAsync

        public async Task DisplayResultAsync()
        {

            byte[] result = await DownLoadFile();
            Console.WriteLine("Downloading complete", result[0]);
        }

        static  Task<byte[]> DownLoadFile()
        {
            FileDownLoader flDl = new FileDownLoader();

            return  Task.Run(() =>
            {
                byte[] result = flDl.Download("test"); 
               return result;
            });
        }

我想在后台执行此任务,但第二项任务应该在第一项任务完成时开始。

FileDownLoader代码:

class FileDownLoader
    {
        public byte[] Download(string url)
        {
            Thread.Sleep(2000);
            return new byte[] { 1, 2, 3, 4 };
        }
    } 

我该怎么用?因为这个任务一起执行

1 个答案:

答案 0 :(得分:1)

这里有几个问题。首先,您需要使用asynchronous file I/O来执行实际的文件下载,这样您就不会阻止线程。看来你的FileDownLoader课程现在只是伪造它,这很好但是至少假装它是异步的:

class FileDownLoader
{
    public async byte[] DownloadAsync(string url)
    {
        await Task.Delay(2000);
        return new byte[] { 1, 2, 3, 4 };
    }
}

允许您执行的操作是删除调用代码中的Task.Run。 (对于这样的I / O绑定工作,异步就是消耗更少的线程,而不是更多。无论何时在异步方法中看到Task.Run,它通常 你做过的一个标志有些不对劲。)

继续,您可以将DisplayResultAsyncDownLoadFile合并到此:

public async Task DownloadAndDisplayResultAsync()
{
    FileDownLoader flDl = new FileDownLoader();
    byte[] result = await flDl.DownloadAsync("test");
    Console.WriteLine("Downloading complete", result[0]);
}

您想要调用上述方法两次,但是您不希望第二次调用在第一次完成之前启动。 await允许您轻松无阻塞地执行此操作,但您只能使用async方法(而不是Main)执行此操作,因此我们在您的控制台应用中引入一种新方法:

static async Task DoWorkAsync()
{
    Downloads test = new Downloads();
    await test.DisplayResultAsync();
    await test.DisplayResultAsync();
}

现在我们只需要从Main调用它。你说你希望下载“在后台”发生,所以你可能想要同时进行一些“前景”工作。这是评论的地方:

static void Main()
{
    var task = DoWorkAsync();
    // do "foreground" work here
    task.Wait();
    Console.ReadLine();
}

作为附注,使用异步代码的另一个经验法则是,永远不应阻止.Wait().Result除{/ 1>之外的的异步调用控制台应用程序的方法。在所有其他情况下使用Main