Я создаю приложение погоды, которое проверяет температуру на службе, которую я сделал:
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 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();
}
}
Проблема проще, чем вы думаете: вы используете BackgroundWorker
, который в основном обертывает поток, который имеет .IsBackground = true
. Такие потоки не будут поддерживать процесс в рабочем состоянии - они будут автоматически отключены при выходе из процесса. Процесс завершится, когда все нефонические потоки будут завершены.
Ваш Main
метод запускает BackgroundWorker
, но затем ничего не делает - Main
выходы, и приложение завершено. Затем BackgroundWorker
отключается в любой точке, в которой он достигнут. Там нет ничего плохого в коде, который он запускает, но приложение закрывается, не давая ему закончить.
EDIT: если вы хотите проверить это, просто поставьте Console.ReadLine()
в конце вашего Main
- он будет поддерживать приложение до тех пор, пока вы не нажмете Enter, и поэтому вы должны увидеть, что ваш поток работает до тех пор, пока вы это сделаете.