简体   繁体   English

Docker中长期运行的C#流程

[英]Long Running C# Process in Docker

I have a Windows Service that I wrote in C#. 我有一个用C#编写的Windows服务。 This "brains" of the app are in a class named Driver . 该应用程序的“大脑”位于名为Driver的类中。 This class asynchronously starts up a bunch of threads to do a number of things. 此类异步启动一堆线程来执行许多操作。 There's nothing "blocking" in this code. 这段代码中没有任何“阻塞”。 The Driver is responsible for starting these threads, listening for specific events, and stopping the threads on these events. 驱动程序负责启动这些线程,侦听特定事件并在这些事件上停止线程。

At this time, I've wrapped this code as a Windows Service. 目前,我已将此代码包装为Windows服务。 The OnStart , OnStop , etc methods are just wrappers into this class. OnStartOnStop等方法只是此类的包装。 The Windows Service runs as I want it to. Windows服务可以按照我的意愿运行。 However, now, I want to run this code in a Docker container. 但是,现在,我想在Docker容器中运行此代码。 My question is, how do I modify this code to become a long running process instead of a Windows Service. 我的问题是,如何修改此代码以使其成为长期运行的过程,而不是Windows Service。

My initial thought was to wrap my code in a Console app. 我最初的想法是将代码包装在控制台应用程序中。 Then, I would move the code from OnStart to the body of the Console app. 然后,我将代码从OnStart移到Console应用程序的主体。 After that code, I would just have a while(true){} statement to keep the console app alive. 在该代码之后,我只需要while(true){}语句即可使控制台应用程序保持活动状态。 However, this feels like a hack. 但是,这感觉像是黑客。

Is this approach a hack? 这是黑客吗? Or, is there a "real" way to do this? 或者,是否有“真正的”方法来做到这一点? If so, what is the recommended approach for having a long running C# app in Docker? 如果是这样,在Docker中具有长期运行的C#应用​​程序的推荐方法是什么?

Using dotnet core 2.1 you can use the IHostedService known from aspnet in a console application as well, provided by Microsoft.Extensions.Hosting. 使用dotnet core 2.1,您还可以在Microsoft.Extensions.Hosting提供的控制台应用程序中使用aspnet已知的IHostedService。 Combine that with C# >= 7.1 (check your project settings), where you can use an async Main method, your code would look something like this: 结合使用C#> = 7.1(检查项目设置),在这里可以使用异步Main方法,您的代码将如下所示:

static async Task Main(string[] args)
{
  var builder = new HostBuilder(); // from Microsoft.Extensions.Hosting

  builder.ConfigureServices(s => s.AddSingleton<IHostedService, YourImplementation>());

  await builder.RunConsoleAsync();
}

A hosting process (eg a Windows Service) is better than a console application that runs in a tight loop ( while(true) {} ). 托管进程(例如Windows Service)比在紧密循环( while(true) {} )中运行的控制台应用程序更好。 Since you intend to run it in a Docker container, I'd suggest looking at AspNet Core, targeting .Net Core so that you can use a Linux base image (which has a smaller image size). 由于您打算在Docker容器中运行它,因此建议您查看以.Net Core为目标的AspNet Core,以便可以使用Linux基本映像(映像大小较小)。 AspNet Core provides a web server (Kestrel) which will be the hosting process in this case. AspNet Core提供了一个Web服务器(Kestrel),在这种情况下,它将作为托管过程。

To run a long running task in AspNet Core, have a look at Asp.Net core long running task . 要在AspNet Core中运行长时间运行的任务,请查看Asp.Net core长期运行任务

Since you want to run your app as Docker container, I guess you also want to run it on Linux. 由于您希望将应用程序作为Docker容器运行,因此我想您也希望在Linux上运行它。 Then I think you can target your code to .NET Core which supports to run on both Windows and Linux (also Mac). 然后,我认为您可以将代码定位到支持在Windows和Linux(以及Mac)上运行的.NET Core。

There's a package named Microsoft.Extensions.Hosting which is a hosting and startup infrastructures for both asp.net core and dotnet core console application, it helps to manage your process to life cycle. 有一个名为Microsoft.Extensions.Hosting的程序包,它是asp.net核心和dotnet核心控制台应用程序的托管和启动基础结构,它有助于管理整个生命周期的过程。 Its ConsoleLifetime class would process the general aplication start/stop method which defined in the interface named IHostedService . 它的ConsoleLifetime类将处理通用复制开始/停止方法,该方法在名为IHostedService的接口中定义。

You just need to implement your own IHostedService (or inherit from the BackgroundService class) and add it to host context within ConfigureServies . 您只需要实现自己的IHostedService (或从BackgroundService类继承)并将其添加到ConfigureServies主机上下文中即可。

Here's a sample hosted service: 这是一个示例托管服务:

public class TimedHostedService : IHostedService, IDisposable
{
    private readonly ILogger _logger;
    private Timer _timer;

    public TimedHostedService(ILogger<TimedHostedService> logger)
    {
        _logger = logger;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, 
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        _logger.LogInformation("Timed Background Service is working.");
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

Then modify your main method: 然后修改您的主要方法:

public class Program
{
    public static async Task Main(string[] args)
    {
        var hostBuilder = new HostBuilder()
             // Add configuration, logging, ...
            .ConfigureServices((hostContext, services) =>
            {
                // Add your services with depedency injection.
                services.AddSingleton<IHostedService, TimedHostedService>();
            });

        await hostBuilder.RunConsoleAsync();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在C#中创建一个长时间运行的进程? - How would I create a long running process in C#? 如何在Winforms C#中使用长时间运行的进程 - how to use a long running process in winforms c# asp.net C# 中长时间运行的进程 - long running process in asp.net C# 在c#中运行一个进程 - running a process in c# 如何在长时间运行的C#.NET CF 2.0进程中显示忙碌指示器? - How to display an busy indicator in a long running C# .NET CF 2.0 process? 执行长时间运行的任务时,显示进程表单的 c# 似乎卡住了 - c# showing a process form seems to get stuck when performing a long running task 如何在C#中使用Windows Service创建计划的长时间运行的进程 - How to create a scheduled long running process using windows service in c# C#-&gt; Windows服务-&gt; WCF ServiceHost-&gt; 如何实现长期运行的过程 - C# -> Windows service -> WCF ServiceHost -> ? How to implement long running process C#具有超时和LoadingForm的长过程 - C# Long process with timeout and LoadingForm 如何在WPF的主UI线程中运行长时间运行的进程时锁定UI(C#中的代码) - How can I lock UI while running the long running process in the main UI Thread in WPF (code in C#)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM