Вот хороший трюк для петли.
Для начала, если вы не хотите, чтобы приложение самоубийственно и оставалось открытым, введите время 2018 года - сделайте нас из HostBuilder!
Вы можете запускать и останавливать приложение и быть асинхронными, выигрывать, выигрывать, выигрывать, поэтому в качестве быстрого примера приведем основную точку входа для моего механизма последних событий:
public static async Task Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
var startup = new Startup();
var hostBuilder = new HostBuilder()
.ConfigureHostConfiguration(startup.ConfigureHostConfiguration)
.ConfigureAppConfiguration(startup.ConfigureAppConfiguration)
.ConfigureLogging(startup.ConfigureLogging)
.ConfigureServices(startup.ConfigureServices)
.Build();
await hostBuilder.RunAsync();
}
Добавление ссылки на пакет nuget в Microsoft.Extensions.Hosting.
Вы можете пропустить все строки запуска ..., если у вас есть DI, чтобы разобраться.
Также вам нужно добавить эту строку в ваш файл проекта:
<LangVersion>latest</LangVersion>
После запуска приложения любая реализация IHostedService запускается автоматически.
Я поместил свой консольный код здесь, вот мой пример этого:
using MassTransit;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Trabalhos.EventsEngine.Messages;
namespace Trabalhos.EventsEngine.ClientExample
{
public class SenderHostedService : IHostedService
{
private readonly IBusControl eventsEngine;
private readonly ILogger<SenderHostedService> logger;
public SenderHostedService(IBusControl eventsEngine, ILogger<SenderHostedService> logger)
{
this.eventsEngine = eventsEngine;
this.logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
var products = new List<(string name, decimal price)>();
Console.WriteLine("Welcome to the Shop");
Console.WriteLine("Press Q key to exit");
Console.WriteLine("Press [0..9] key to order some products");
Console.WriteLine(string.Join(Environment.NewLine, Products.Select((x, i) => $"[{i}]: {x.name} @ {x.price:C}")));
for (;;)
{
var consoleKeyInfo = Console.ReadKey(true);
if (consoleKeyInfo.Key == ConsoleKey.Q)
{
break;
}
if (char.IsNumber(consoleKeyInfo.KeyChar))
{
var product = Products[(int)char.GetNumericValue(consoleKeyInfo.KeyChar)];
products.Add(product);
Console.WriteLine($"Added {product.name}");
}
if (consoleKeyInfo.Key == ConsoleKey.Enter)
{
await eventsEngine.Publish<IDummyRequest>(new
{
requestedData = products.Select(x => new { Name = x.name, Price = x.price }).ToList()
});
Console.WriteLine("Submitted Order");
products.Clear();
}
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private static readonly IReadOnlyList<(string name, decimal price)> Products = new List<(string, decimal)>
{
("Bread", 1.20m),
("Milk", 0.50m),
("Rice", 1m),
("Buttons", 0.9m),
("Pasta", 0.9m),
("Cereals", 1.6m),
("Chocolate", 2m),
("Noodles", 1m),
("Pie", 1m),
("Sandwich", 1m),
};
}
}
Это будет срабатывать, работать и продолжать работать.
Крутой вещью здесь также является цикл for (;;), это хитрый трюк, позволяющий запускать его в цикле, чтобы вы могли заново делать вещи снова и снова, хостинг просто означает, что вам не нужно беспокоиться о поддерживая консоль.
У меня даже есть клавиша Escape, как вы хотите:
if (consoleKeyInfo.Key == ConsoleKey.Q)
{
break;
}
Более подробный пример использования размещенной установки можно найти по этой ссылке https://jmezach.github.io/2017/10/29/having-fun-with-the-.net-core-generic-host/
Проходит через все это, поэтому должно помочь.