Как я могу создать консольное приложение, которое utlilitize async / await

1

Я создаю приложение погоды, которое проверяет температуру на службе, которую я сделал:

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 консольное приложение просто завершает работу.

Теги:
async-await
asynchronous

2 ответа

4

В дополнение к ответу Дэна Пузи, нет особого смысла в назначении метода async void в качестве обработчика событий для BackgroundWorker.

Ваш рабочий метод bgw_DoWork вернется, и фоновый поток будет завершен, как только точка выполнения достигнет первого await внутри bgw_DoWork. Задача bot.Update скорее всего, все еще будет bot.Update в этот момент.

Здесь вам не нужен BackgroundWorker. Код может быть простым:

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

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

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

Проблема проще, чем вы думаете: вы используете BackgroundWorker, который в основном обертывает поток, который имеет .IsBackground = true. Такие потоки не будут поддерживать процесс в рабочем состоянии - они будут автоматически отключены при выходе из процесса. Процесс завершится, когда все нефонические потоки будут завершены.

Ваш Main метод запускает BackgroundWorker, но затем ничего не делает - Main выходы, и приложение завершено. Затем BackgroundWorker отключается в любой точке, в которой он достигнут. Там нет ничего плохого в коде, который он запускает, но приложение закрывается, не давая ему закончить.

EDIT: если вы хотите проверить это, просто поставьте Console.ReadLine() в конце вашего Main - он будет поддерживать приложение до тех пор, пока вы не нажмете Enter, и поэтому вы должны увидеть, что ваш поток работает до тех пор, пока вы это сделаете.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню