解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# ÇáÁ¿¼¶Ó¦ÓÃÖ÷»ú Host
## ¸ÅÊö
`Host` ÊÇ NewLife.Core ÖеÄÇáÁ¿¼¶Ó¦ÓÃÖ÷»ú£¬ÌṩӦÓóÌÐòÉúÃüÖÜÆÚ¹ÜÀí¹¦ÄÜ¡£Ö§³ÖÍйܶà¸öºǫ́·þÎñ£¬×Ô¶¯´¦ÀíÆô¶¯¡¢Í£Ö¹¡¢ÓÅÑÅÍ˳öµÈ³¡¾°£¬ÌرðÊʺϿØÖÆÌ¨Ó¦Óᢺǫ́·þÎñ¡¢Î¢·þÎñµÈ³¡¾°¡£
**ÃüÃû¿Õ¼ä**£º`NewLife.Model`
**ÎĵµµØÖ·**£ºhttps://newlifex.com/core/host
## ºËÐÄÌØÐÔ
- **·þÎñÍйÜ**£ºÖ§³Ö×¢²áºÍ¹ÜÀí¶à¸ö `IHostedService` ·þÎñ
- **ÉúÃüÖÜÆÚ¹ÜÀí**£º×Ô¶¯´¦ÀíÆô¶¯¡¢Í£Ö¹¡¢Òì³£»Ø¹ö
- **ÓÅÑÅÍ˳ö**£ºÏìÓ¦ Ctrl+C¡¢SIGINT¡¢SIGTERM µÈϵͳÐźÅ
- **¿çƽ̨**£ºÖ§³Ö Windows¡¢Linux¡¢macOS
- **ÒÀÀµ×¢Èë**£ºÓë `ObjectContainer` Éî¶È¼¯³É
- **³¬Ê±¿ØÖÆ**£ºÖ§³ÖÉèÖÃ×î´óÔËÐÐʱ¼ä
## ¿ìËÙ¿ªÊ¼
```csharp
using NewLife.Model;
// ´´½¨Ö÷»ú
var host = new Host(ObjectContainer.Provider);
// Ìí¼Óºǫ́·þÎñ
host.Add<MyBackgroundService>();
host.Add<AnotherService>();
// ÔËÐУ¨×èÈûÖ±µ½ÊÕµ½Í˳öÐźţ©
host.Run();
```
## API ²Î¿¼
### IHostedService ½Ó¿Ú
ºǫ́·þÎñ±ØÐëʵÏִ˽ӿڣº
```csharp
public interface IHostedService
{
/// <summary>¿ªÊ¼·þÎñ</summary>
Task StartAsync(CancellationToken cancellationToken);
/// <summary>Í£Ö¹·þÎñ</summary>
Task StopAsync(CancellationToken cancellationToken);
}
```
**ʵÏÖʾÀý**£º
```csharp
public class MyBackgroundService : IHostedService
{
private CancellationTokenSource? _cts;
private Task? _task;
public Task StartAsync(CancellationToken cancellationToken)
{
XTrace.WriteLine("MyBackgroundService Æô¶¯");
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
_task = ExecuteAsync(_cts.Token);
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
XTrace.WriteLine("MyBackgroundService ֹͣ");
_cts?.Cancel();
if (_task != null)
await Task.WhenAny(_task, Task.Delay(5000, cancellationToken));
}
private async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
// Ö´Ðкǫ́ÈÎÎñ
XTrace.WriteLine("ºǫ́ÈÎÎñÖ´ÐÐÖÐ...");
await Task.Delay(1000, stoppingToken);
}
}
}
```
### Host Àà
#### ¹¹Ô캯Êý
```csharp
public Host(IServiceProvider serviceProvider)
```
ͨ¹ý·þÎñÌṩÕß´´½¨Ö÷»úʵÀý¡£
**ʾÀý**£º
```csharp
// ʹÓÃÈ«¾ÖÈÝÆ÷
var host = new Host(ObjectContainer.Provider);
// ʹÓÃ×Ô¶¨ÒåÈÝÆ÷
var ioc = new ObjectContainer();
ioc.AddSingleton<ILogger, ConsoleLogger>();
var host = new Host(ioc.BuildServiceProvider());
```
#### Add - Ìí¼Ó·þÎñ
```csharp
// Ìí¼Ó·þÎñÀàÐÍ
void Add<TService>() where TService : class, IHostedService
// Ìí¼Ó·þÎñʵÀý
void Add(IHostedService service)
```
**ʾÀý**£º
```csharp
var host = new Host(ObjectContainer.Provider);
// ͨ¹ýÀàÐÍÌí¼Ó
host.Add<MyBackgroundService>();
host.Add<DataSyncService>();
// ͨ¹ýʵÀýÌí¼Ó
var service = new CustomService(config);
host.Add(service);
```
#### Run / RunAsync - ÔËÐÐÖ÷»ú
```csharp
// ͬ²½ÔËÐУ¨×èÈû£©
void Run()
// Òì²½ÔËÐÐ
Task RunAsync()
```
ÔËÐÐÖ÷»ú£¬Æô¶¯ËùÓзþÎñ£¬È»ºó×èÈûµÈ´ýÍ˳öÐźš£
**ʾÀý**£º
```csharp
// ͬ²½ÔËÐÐ
host.Run();
// Òì²½ÔËÐÐ
await host.RunAsync();
// Òì²½ÔËÐкó¼ÌÐøÆäËû²Ù×÷
_ = host.RunAsync();
// ÆäËû´úÂë...
```
#### StartAsync / StopAsync
```csharp
Task StartAsync(CancellationToken cancellationToken)
Task StopAsync(CancellationToken cancellationToken)
```
ÊÖ¶¯¿ØÖÆÆô¶¯ºÍÍ£Ö¹¡£
**ʾÀý**£º
```csharp
using var cts = new CancellationTokenSource();
// Æô¶¯·þÎñ
await host.StartAsync(cts.Token);
// ×öһЩ¹¤×÷...
await Task.Delay(10000);
// ÊÖ¶¯Í£Ö¹
await host.StopAsync(cts.Token);
```
#### Close - ¹Ø±ÕÖ÷»ú
```csharp
void Close(String? reason)
```
Ö÷¶¯¹Ø±ÕÖ÷»ú£¬´¥·¢Í£Ö¹Á÷³Ì¡£
**ʾÀý**£º
```csharp
// ij¸öÌõ¼þ´¥·¢¹Ø±Õ
if (shouldShutdown)
{
host.Close("Ìõ¼þ´¥·¢¹Ø±Õ");
}
```
#### MaxTime ÊôÐÔ
```csharp
public Int32 MaxTime { get; set; } = -1;
```
×î´óÖ´ÐÐʱ¼ä£¨ºÁÃ룩¡£Ä¬ÈÏ -1 ±íʾÓÀ¾ÃÔËÐС£
**ʾÀý**£º
```csharp
var host = new Host(ObjectContainer.Provider);
host.MaxTime = 60_000; // ×î¶àÔËÐÐ60Ãë
host.Add<MyService>();
host.Run(); // 60Ãëºó×Ô¶¯Í£Ö¹
```
### ¾²Ì¬·½·¨
#### RegisterExit - ×¢²áÍ˳öʼþ
```csharp
// ¿ÉÄܱ»¶à´Îµ÷ÓÃ
static void RegisterExit(EventHandler onExit)
// ½öÖ´ÐÐÒ»´Î
static void RegisterExit(Action onExit)
```
×¢²áÓ¦ÓÃÍ˳öʱµÄ»Øµ÷º¯Êý¡£
**ʾÀý**£º
```csharp
// ×¢²áÍ˳öÇåÀíº¯Êý
Host.RegisterExit(() =>
{
XTrace.WriteLine("Ó¦ÓÃÕýÔÚÍ˳ö£¬Ö´ÐÐÇåÀí...");
CleanupResources();
});
// ´ø²ÎÊýµÄ»Øµ÷
Host.RegisterExit((sender, e) =>
{
XTrace.WriteLine($"ÊÕµ½Í˳öÐźÅ: {sender}");
});
```
## ÈÝÆ÷¼¯³É
### AddHostedService À©Õ¹·½·¨
```csharp
// ͨ¹ýÀàÐÍ×¢²á
IObjectContainer AddHostedService<THostedService>()
// ͨ¹ý¹¤³§×¢²á
IObjectContainer AddHostedService<THostedService>(
Func<IServiceProvider, THostedService> factory)
```
**ʾÀý**£º
```csharp
var ioc = ObjectContainer.Current;
// ×¢²áºǫ́·þÎñ
ioc.AddHostedService<MyBackgroundService>();
ioc.AddHostedService<DataSyncService>();
// ʹÓù¤³§
ioc.AddHostedService(sp =>
{
var config = sp.GetRequiredService<AppConfig>();
return new ConfigurableService(config);
});
// ´´½¨Ö÷»ú²¢ÔËÐÐ
var host = new Host(ioc.BuildServiceProvider());
host.Run();
```
## ʹÓó¡¾°
### 1. ¼òµ¥ºǫ́·þÎñ
```csharp
class Program
{
static void Main()
{
var ioc = ObjectContainer.Current;
ioc.AddHostedService<WorkerService>();
var host = new Host(ioc.BuildServiceProvider());
host.Run();
}
}
public class WorkerService : IHostedService
{
private Timer? _timer;
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(DoWork, null, 0, 5000);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Dispose();
return Task.CompletedTask;
}
private void DoWork(Object? state)
{
XTrace.WriteLine($"¹¤×÷ÖÐ... {DateTime.Now}");
}
}
```
### 2. ¶à·þÎñÐ×÷
```csharp
class Program
{
static void Main()
{
var ioc = ObjectContainer.Current;
// ×¢²á¹²ÏíÒÀÀµ
ioc.AddSingleton<IMessageQueue, RedisMessageQueue>();
ioc.AddSingleton<ILogger, FileLogger>();
// ×¢²á¶à¸öºǫ́·þÎñ
ioc.AddHostedService<MessageConsumerService>();
ioc.AddHostedService<HealthCheckService>();
ioc.AddHostedService<MetricsCollectorService>();
var host = new Host(ioc.BuildServiceProvider());
host.Run();
}
}
```
### 3. ¶¨Ê±ÈÎÎñ·þÎñ
```csharp
public class ScheduledTaskService : IHostedService
{
private readonly ILogger _logger;
private TimerX? _timer;
public ScheduledTaskService(ILogger logger)
{
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
// ÿÌìÁ賿2µãÖ´ÐÐ
_timer = new TimerX(ExecuteTask, null, "0 0 2 * * *");
_logger.Info("¶¨Ê±ÈÎÎñ·þÎñÒÑÆô¶¯");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Dispose();
_logger.Info("¶¨Ê±ÈÎÎñ·þÎñÒÑÍ£Ö¹");
return Task.CompletedTask;
}
private void ExecuteTask(Object? state)
{
_logger.Info("Ö´Ðж¨Ê±ÈÎÎñ...");
// ÈÎÎñÂß¼
}
}
```
### 4. ´ø³¬Ê±µÄ²âÊÔÔËÐÐ
```csharp
class Program
{
static async Task Main()
{
var ioc = ObjectContainer.Current;
ioc.AddHostedService<TestService>();
var host = new Host(ioc.BuildServiceProvider());
host.MaxTime = 30_000; // 30Ãëºó×Ô¶¯Í£Ö¹
await host.RunAsync();
Console.WriteLine("²âÊÔÍê³É");
}
}
```
### 5. ÓÅÑÅÍ˳ö´¦Àí
```csharp
public class GracefulService : IHostedService
{
private readonly List<Task> _runningTasks = new();
private CancellationTokenSource? _cts;
public Task StartAsync(CancellationToken cancellationToken)
{
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
// Æô¶¯¶à¸ö¹¤×÷ÈÎÎñ
for (var i = 0; i < 5; i++)
{
_runningTasks.Add(WorkerLoop(i, _cts.Token));
}
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
XTrace.WriteLine("ÊÕµ½Í£Ö¹Ðźţ¬µÈ´ýÈÎÎñÍê³É...");
// È¡Ïû¹¤×÷ÈÎÎñ
_cts?.Cancel();
// µÈ´ýËùÓÐÈÎÎñÍê³É£¬×î¶àµÈ´ý10Ãë
var timeout = Task.Delay(10_000, cancellationToken);
var allTasks = Task.WhenAll(_runningTasks);
await Task.WhenAny(allTasks, timeout);
XTrace.WriteLine("ËùÓÐÈÎÎñÒÑÍ£Ö¹");
}
private async Task WorkerLoop(Int32 id, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
XTrace.WriteLine($"Worker {id} Ö´ÐÐÖÐ...");
await Task.Delay(1000, token).ConfigureAwait(false);
}
}
}
```
## Í˳öÐźŴ¦Àí
Host ×Ô¶¯´¦ÀíÒÔÏÂÍ˳öÐźţº
| ÐźŠ| ƽ̨ | ˵Ã÷ |
|------|------|------|
| Ctrl+C | ȫƽ̨ | ¿ØÖÆÌ¨ÖÐ¶Ï |
| SIGINT | Linux/macOS | ÖжÏÐźŠ|
| SIGTERM | Linux/macOS | ÖÕÖ¹Ðźţ¨Docker ĬÈÏ£© |
| SIGQUIT | Linux/macOS | Í˳öÐźŠ|
| ProcessExit | ȫƽ̨ | ½ø³ÌÍ˳öʼþ |
**Docker ²¿Êð×¢Òâ**£º
```dockerfile
# ʹÓà exec ÐÎʽ£¬È·±£ÐźÅÕýÈ·´«µÝ
CMD ["dotnet", "MyApp.dll"]
# »òÕßʹÓà tini ×÷Ϊ init ½ø³Ì
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["dotnet", "MyApp.dll"]
```
## ×î¼Ñʵ¼ù
### 1. ·þÎñÆô¶¯Ë³Ðò
·þÎñ°´×¢²á˳ÐòÆô¶¯£¬°´·´Ïò˳ÐòÍ£Ö¹£º
```csharp
ioc.AddHostedService<DatabaseService>(); // ÏÈÆô¶¯£¬ºóÍ£Ö¹
ioc.AddHostedService<CacheService>(); // µÚ¶þ
ioc.AddHostedService<ApiService>(); // ºóÆô¶¯£¬ÏÈÍ£Ö¹
```
### 2. Òì³£´¦Àí
Æô¶¯Ê§°Üʱ»á×Ô¶¯»Ø¹öÒÑÆô¶¯µÄ·þÎñ£º
```csharp
public class MyService : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
// Èç¹ûÅ׳öÒì³££¬ÒÑÆô¶¯µÄ·þÎñ»á±»×Ô¶¯Í£Ö¹
await InitializeAsync();
}
public Task StopAsync(CancellationToken cancellationToken)
{
// È·±£Í£Ö¹Âß¼²»Å׳öÒì³£
try
{
return CleanupAsync();
}
catch (Exception ex)
{
XTrace.WriteException(ex);
return Task.CompletedTask;
}
}
}
```
### 3. ×ÊÔ´ÊÍ·Å
ʵÏÖ `IDisposable` ½øÐжîÍâÇåÀí£º
```csharp
public class ResourceService : IHostedService, IDisposable
{
private FileStream? _file;
public Task StartAsync(CancellationToken cancellationToken)
{
_file = File.OpenWrite("data.log");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public void Dispose()
{
_file?.Dispose();
}
}
```
## Ïà¹ØÁ´½Ó
- [¶ÔÏóÈÝÆ÷ ObjectContainer](/NewLife/X/Blob/master/Doc/object_container-¶ÔÏóÈÝÆ÷ObjectContainer.md)
- [¸ß¼¶¶¨Ê±Æ÷ TimerX](/NewLife/X/Blob/master/Doc/timerx-¸ß¼¶¶¨Ê±Æ÷TimerX.md)
- [ÈÕ־ϵͳ ILog](/NewLife/X/Blob/master/Doc/log-ÈÕÖ¾ILog.md)
|