如何创建一个可以使异步/等待的控制台应用程序

时间:2014-05-21 08:26:42

标签: c# asynchronous async-await

我正在创建一个天气应用程序,用于调查我所提供服务的温度:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Weather
{
    class Program
    {
        static BackgroundWorker bgw;

        static void Main(string[] args)
        {
            bgw = new BackgroundWorker();
            bgw.DoWork += bgw_DoWork;
            bgw.RunWorkerAsync();
        }

        static async void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            Weather bot = new Weather();

            if (bot.IsRunning)
            {
                await bot.Update();
            }
        }
    }

    public class Weather
    {
        public bool IsRunning { get; set; }

        private DateTime lastUpdated;

        public Weather()
        {
            IsRunning = true;

            lastUpdated = DateTime.Now.AddDays(-1);
        }

        public async Task<bool> Update()
        {
            if (lastUpdated < DateTime.Now)
            {
                lastUpdated = DateTime.Now.AddSeconds(30);

                // temperature
                double value = await GetLatestValue("New York");
            }

            return true;
        }

        private async Task<double> GetLatestValue(string city)
        {
            string url = "http://www" + city;

            var client = new WebClient();
            string data = await client.DownloadStringTaskAsync(url);

            return 4.3;
        }
    }
}

这里的问题是它似乎不起作用? GetLatesValue函数只是乱码,为了测试目的只返回4.3。

await GetLatestValue控制台应用程序退出时会发生什么。

2 个答案:

答案 0 :(得分:4)

问题比你想象的要简单:你正在运行BackgroundWorker,它基本上包含了一个.IsBackground = true的线程。这样的线程不会使进程保持活动状态 - 当进程退出时它们将自动关闭。当所有 - 背景线程完成时,该过程将退出。

您的Main方法启动BackgroundWorker,但之后不执行任何操作 - Main退出,并且应用程序已完成。然后BackgroundWorker会在它到达的任何地方关闭。它运行的代码没有任何问题 - 但应用程序正在关闭而不让它完成。

编辑:如果您想对此进行测试,只需在Console.ReadLine()的末尾添加Main - 它就会让应用程序保持活着状态,直到您按下为止输入,所以你应该看到你的线程运行,直到你这样做。

答案 1 :(得分:4)

除了Dan Puzey's answer之外,首先将async void方法指定为BackgroundWorker的事件处理程序没有多大意义。

一旦执行点到达bgw_DoWork内的第一个await,您的工人方法bgw_DoWork将返回并且后台线程将完成。 bot.Update任务很可能在那时仍未决定。

此处您不需要BackgroundWorker。代码可以这么简单:

static void Main(string[] args)
{
    DoWorkAsync().Wait();
}

static async Task DoWorkAsync()
{
    Weather bot = new Weather();

    if (bot.IsRunning)
    {
        await bot.Update();
    }
}