IHostedService 定义一个长时间运行的服务

IHostedService 是一个 .NET Core 接口,用于定义一个长时间运行的服务,可以在 ASP.NET Core 应用程序中使用。它提供了两个方法:

  1. StartAsync:在应用程序启动时调用,用于启动服务。

  2. StopAsync:在应用程序关闭时调用,用于停止服务。

IHostedService 接口可以用于实现各种后台任务,例如:

  1. 定时任务:使用 Timer 或 CancellationTokenSource 和 Task.Delay 实现。

  2. 后台处理任务:使用 Task.Run 在后台线程中执行长时间运行的代码。

  3. 后台队列任务:使用消息队列实现后台任务的处理。

使用 IHostedService 接口的好处是可以很容易地将后台任务集成到 ASP.NET Core 应用程序中,同时也可以很容易地控制后台任务的启动和停止。

using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Authorization.WebApi
{
    /// <summary>
    /// 官方介绍主要是用来实现实现后台任务
    /// </summary>
    public class BackgroundService : IHostedService, IDisposable
    {
        private readonly ILogger _logger;
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger"></param>
        public WpBackgroundService(ILogger logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 服务开始执行的代码
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _ = DoWorkAsync();
            await Task.CompletedTask;
        }

        /// <summary>
        /// 业务逻辑
        /// </summary>
        /// <returns></returns>
        private async Task DoWorkAsync()
        {
            await Task.Run(async () =>
              {
                  while (!_cts.IsCancellationRequested)
                  {
                      Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
                      await Task.Delay(TimeSpan.FromSeconds(5), _cts.Token);
                  }
              }, _cts.Token);
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            _cts.Cancel();
            await Task.CompletedTask;
        }

        /// <summary>
        /// 释放
        /// </summary>
        public void Dispose()
        {
            _cts.Dispose();
        }
    }
}
  1. 在后台任务类中创建一个 CancellationTokenSource 对象,用于取消后台任务。

  2. 在后台任务中使用无限循环,直到 CancellationTokenSource 对象被取消。

  3. 在循环中使用 Task.Delay 方法来等待一定时间间隔,并检查 CancellationTokenSource 是否已被取消。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于MVVM设计模式和IHostedService的登录程序示例,其中使用了WPF作为UI框架,密码加密采用了SHA256算法: MainWindow.xaml: ```xml <Window x:Class="LoginApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:LoginApp" Title="Login" Height="250" Width="400"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Content="Username:" /> <TextBox Grid.Row="0" Grid.Column="1" Margin="5" Text="{Binding Username}" /> <Label Grid.Row="1" Grid.Column="0" Content="Password:" /> <PasswordBox Grid.Row="1" Grid.Column="1" Margin="5" Password="{Binding Password}" /> <TextBlock Grid.Row="2" Grid.Column="1" Margin="5" Foreground="Red" Text="{Binding Error}" /> <Button Grid.Row="3" Grid.Column="1" Margin="5" Content="Login" Command="{Binding LoginCommand}" /> </Grid> </Window> ``` MainWindowViewModel.cs: ```csharp using System; using System.ComponentModel; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; namespace LoginApp { public class MainWindowViewModel : INotifyPropertyChanged { private string _username; private string _password; private string _error; public string Username { get => _username; set { _username = value; OnPropertyChanged(nameof(Username)); } } public string Password { get => _password; set { _password = value; OnPropertyChanged(nameof(Password)); } } public string Error { get => _error; set { _error = value; OnPropertyChanged(nameof(Error)); } } public ICommand LoginCommand { get; } public event PropertyChangedEventHandler PropertyChanged; public MainWindowViewModel() { LoginCommand = new RelayCommand(async () => await LoginAsync()); } private async Task LoginAsync() { Error = null; // Validate input if (string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(Password)) { Error = "Username and password are required."; return; } // Hash password var passwordHash = HashPassword(Password); // Simulate login request var token = await Task.Run(() => { Thread.Sleep(2000); // Simulate network delay if (Username == "admin" && passwordHash == "AC3C1E5F9A4C91E4DE7D6F5A3B85F0B2F1854D7B9D9AAB2B6DFAF6F9E2C3E8E4") { return Guid.NewGuid().ToString(); } else { return null; } }); if (token != null) { // Login successful, navigate to main window var mainWindow = new MainWindow(); mainWindow.DataContext = new MainViewModel(token); mainWindow.Show(); Application.Current.MainWindow.Close(); } else { // Login failed Error = "Invalid username or password."; } } private static string HashPassword(string password) { using var sha256 = SHA256.Create(); var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password)); var sb = new StringBuilder(); foreach (var b in bytes) { sb.Append(b.ToString("X2")); } return sb.ToString(); } protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } ``` MainViewModel.cs: ```csharp using System.ComponentModel; using System.Windows.Input; namespace LoginApp { public class MainViewModel : INotifyPropertyChanged { private string _token; public string Token { get => _token; set { _token = value; OnPropertyChanged(nameof(Token)); } } public ICommand LogoutCommand { get; } public event PropertyChangedEventHandler PropertyChanged; public MainViewModel(string token) { Token = token; LogoutCommand = new RelayCommand(Logout); } private void Logout() { // Navigate back to login window var loginWindow = new MainWindow(); loginWindow.Show(); Application.Current.MainWindow.Close(); } protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } ``` RelayCommand.cs: ```csharp using System; using System.Windows.Input; namespace LoginApp { public class RelayCommand : ICommand { private readonly Action _execute; private readonly Func<bool> _canExecute; public RelayCommand(Action execute, Func<bool> canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) => _canExecute == null || _canExecute(); public void Execute(object parameter) => _execute(); public void RaiseCanExecuteChanged() => CommandManager.InvalidateRequerySuggested(); } } ``` LoginHostedService.cs: ```csharp using Microsoft.Extensions.Hosting; using System.Threading; using System.Threading.Tasks; using System.Windows; namespace LoginApp { public class LoginHostedService : IHostedService { private readonly Window _loginWindow; public LoginHostedService(Window loginWindow) { _loginWindow = loginWindow; } public Task StartAsync(CancellationToken cancellationToken) { // Show login window _loginWindow.Show(); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { // Close login window _loginWindow.Close(); return Task.CompletedTask; } } } ``` App.xaml.cs: ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Windows; namespace LoginApp { public partial class App : Application { private IHost _host; protected override async void OnStartup(StartupEventArgs e) { base.OnStartup(e); _host = Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { services.AddSingleton<Window>(new MainWindow()); services.AddSingleton<LoginHostedService>(); }) .Build(); await _host.StartAsync(); } protected override async void OnExit(ExitEventArgs e) { base.OnExit(e); await _host.StopAsync(); _host.Dispose(); } } } ``` 在以上代码中,MainWindowViewModel类包含了登录窗口的数据和行为,其中LoginCommand命令用于处理登录操作。当用户点击登录按钮时,LoginAsync方法被执行,该方法首先验证输入是否合法,然后对密码进行哈希处理,并模拟发送登录请求。如果请求成功,程序会跳转到主窗口,否则会提示错误信息。 MainViewModel类则包含了主窗口的数据和行为,其中LogoutCommand命令用于处理注销操作。当用户点击注销按钮时,Logout方法被执行,该方法会关闭主窗口,并跳转回登录窗口。 RelayCommand类是一个通用的命令实现,用于将委托转换为ICommand接口。 LoginHostedService类继承自IHostedService接口,用于在应用程序启动时显示登录窗口,并在应用程序关闭时关闭登录窗口。 App类则用于配置和启动应用程序,其中使用了Microsoft.Extensions.Hosting和Microsoft.Extensions.DependencyInjection库来实现依赖注入和应用程序生命周期管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值