myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Rund um die Programmierung » Windows Dienst stoppt nach erster Ausführung
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Windows Dienst stoppt nach erster Ausführung

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
CoderboyPB CoderboyPB ist männlich
myCSharp.de-Mitglied

Dabei seit: 09.01.2008
Beiträge: 278
Entwicklungsumgebung: Visualstudio 2019
Herkunft: Paderborn


CoderboyPB ist offline

Windows Dienst stoppt nach erster Ausführung

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
die statische Funktion Run() der Klasse Bot wird nur einmal ausgeführt, dann stoppt der Dienst automatisch.
Was mache ich falsch?

C#-Code:
public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .WriteTo.File(@"C:\SosaBot\LogFile.txt")
                .CreateLogger();

            try
            {
                Log.Information("Starting up the Service");
                CreateHostBuilder(args).Build().Run();
                return;
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "-ther was a problem, starting the service");
                return;
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)
                .UseWindowsService()
                .ConfigureServices((hostContext, services) =>
                {
                services.AddHostedService<Worker>();
                })
                .UseSerilog();
        }
    }

C#-Code:
public class Worker : BackgroundService
    {
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                await Bot.Run();
                await Task.Delay(1000 * 60 * 3, stoppingToken);
            }
        }
    }

C#-Code:
public static class Bot
    {
        public static async Task Run()
        {
            Log.Information("Starting Bot");

            var userClient = new TwitterClient(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);

            (await userClient.Search.SearchTweetsAsync("Sportsfreund Sosa"))
                .ToList()
                .ForEach(async tweet =>
                {
                    Log.Information($"retweeting: {tweet.FullText}");
                    await userClient.Tweets.PublishRetweetAsync(tweet.Id);
                });

            Log.Information("Stopping Bot");
        }
    }

PS: Die Zugangsdaten sind da, habe sie aber hier heraus genommen.
Neuer Beitrag 14.01.2021 17:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.447
Herkunft: BW


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Den einzigen Fehler, den ich so sehe ist, dass Dein Logging kein Sinn macht.
- Du registierst nen statischen Logger
- Du registrierst nochmal Serilog


Normalerweise registriert man Serilog so:

C#-Code:
        public static int Main(string[] args)
            => RunHostBuilder<Startup>(args);

        public static int RunHostBuilder<TStartup>(string[] args) where TStartup : class
        {
            try
            {
                using IHost host = CreateHostBuilder<TStartup>(args).Build();
                host.Run();

                return 0;
            }
            catch (Exception ex)
            {
                // Log.Logger will likely be internal type "Serilog.Core.Pipeline.SilentLogger"
                // This will log into Console, when app fails on startup
                if (Log.Logger == null || Log.Logger.GetType().Name == "SilentLogger")
                {
                    Log.Logger = new LoggerConfiguration()
                        .MinimumLevel.Debug()
                        .WriteTo.Console()
                        .CreateLogger();
                }

                Log.Fatal(ex, "Host terminated unexpectedly");

                return 1; /* 0 = ok, 1 = general error */
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }

        public static IHostBuilder CreateHostBuilder<TStartup>(string[] args)
            where TStartup : class
            => Host.CreateDefaultBuilder(args)
                .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<TStartup>()
                        .CaptureStartupErrors(true);
                });

Oder eben noch

C#-Code:
                .UseSerilog((hostingContext, loggerConfiguration) =>
                {
                    loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration);
                })

Wenn Du Serilog über die appsettings.json verwalten willst.

Ansonsten solltest Du ja über Debugging herausfinden, warum der "Worker" (jetzt weiß ich auch, wieso Du im anderen Thread von Worker sprichst; dass Du damit nen BackgroundService meinst haste nicht verraten) sich und damit den Windows Service beendest.
Dazu musst Du nur die Start / Stop etc Methoden entsprechend implementieren und kannst dann rein steppen.

Damit relativiert sich übrigens auch meine Antwort im Azure Thread.
Du musst bei Fragen unbedingt den potentiellen Helfern mitteilen, von was Du sprichst.....

 Lösung siehe hier.
Neuer Beitrag 14.01.2021 17:33 Beiträge des Benutzers | zu Buddylist hinzufügen
CoderboyPB CoderboyPB ist männlich
myCSharp.de-Mitglied

Dabei seit: 09.01.2008
Beiträge: 278
Entwicklungsumgebung: Visualstudio 2019
Herkunft: Paderborn

Themenstarter Thema begonnen von CoderboyPB

CoderboyPB ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

1. zu dem Service:

Die Twitter Libary hatte ne Exception geworfen, die aber dummerweise nicht protokolliert wurde ...
Hab das Ganze entdeckt, als ich das noch mal als Standalone Applikation habe laufen lassen.

Die Exception wurde ausgelöst, dadurch, dass Retweets geretweeted wurden.
Fange die Exception jetzt ab und verlasse dann die Schleife direkt. Vorher habe ich die Tweets natürich chronologisch geordnet:

C#-Code:
public static async Task Run()
        {
            var userClient = new TwitterClient(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);

            var tweets = (await userClient.Search.SearchTweetsAsync("Sportsfreund Sosa"))
                 .OrderByDescending(tweet => tweet.CreatedAt)
                 .ToList();

            foreach (var tweet in tweets)
            {
                try
                {
                    await userClient.Tweets.PublishRetweetAsync(tweet.Id);
                    Log.Information($"Retweeted: {{ {tweet.FullText} }}");
                }
                catch (TwitterException)
                {
                    return;
                }
            }
        }

aber das funktioniert jetzt :-)

Was mich halt ärgert ist, dass die Exception nicht geloggt wurde, hätte mir einiges an Arbeit erspart ...

Zum Thema Serilog:
Das habe ich von einem Youtube Video von Tim Corey, ich selber kenne mich mit Serilog nicht aus, aber es scheint sehr mächtig zu sein, so dass ich es mir mal anschauen werde.
Neuer Beitrag 14.01.2021 20:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
CoderboyPB CoderboyPB ist männlich
myCSharp.de-Mitglied

Dabei seit: 09.01.2008
Beiträge: 278
Entwicklungsumgebung: Visualstudio 2019
Herkunft: Paderborn

Themenstarter Thema begonnen von CoderboyPB

CoderboyPB ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Nachtrag:
Der statische Logger I ST Serilog, mit UseSerilog wird dann das Programm angewiesen, Serilog zu nutzen.
So in etwa hat Tim Corey es in seinem Video erklärt.
Neuer Beitrag 14.01.2021 20:38 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.447
Herkunft: BW


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von CoderboyPB:
Der statische Logger I ST Serilog, mit UseSerilog wird dann das Programm angewiesen, Serilog zu nutzen.

Nein, UseSerilog ist ein Shortcut für die Service Konfiguration und injiziert dabei die Factory.
Einfach mal in den  Quellcode schauen.

Zitat von CoderboyPB:
Die Twitter Libary hatte ne Exception geworfen, die aber dummerweise nicht protokolliert wurde ...

Setz den Logger korrekt, dann wird sie protokolliert.
Aber wenn Du meinst, dass meine Aussage falsch ist, dann lass es eben so - musst Du wissen :-)
Neuer Beitrag 14.01.2021 20:56 Beiträge des Benutzers | zu Buddylist hinzufügen
ClaraSoft
myCSharp.de-Mitglied

Dabei seit: 23.03.2020
Beiträge: 7


ClaraSoft ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich nutze Dependency Injection um meinen Logger zu bekommen. Dafür nutze ich das Interface ILogger<T>, was eigentlich sogar der standard Weg ist bzw sein sollte. Den kann ich sogar mit NLog konfigurieren. Ob der auch mit Serilog konfigurierbar ist weiß ich nicht.

C#-Code:
private readonly ILogger<MqttSubcriptionWorker> logger;

public MqttSubcriptionWorker(ILogger<MqttSubcriptionWorker> logger)
{
    this.logger = logger;
}
Neuer Beitrag 14.01.2021 21:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
CoderboyPB CoderboyPB ist männlich
myCSharp.de-Mitglied

Dabei seit: 09.01.2008
Beiträge: 278
Entwicklungsumgebung: Visualstudio 2019
Herkunft: Paderborn

Themenstarter Thema begonnen von CoderboyPB

CoderboyPB ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Das ist auch der mir bekannte Weg.
Aber wie gesagt, hier zählte einfach nur das Ergebnis.

Wen es interessiert hier das Video. Ab ca. min 20:15
 https://www.youtube.com/watch?v=PzrTiz_NRKA
Neuer Beitrag 14.01.2021 21:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.447
Herkunft: BW


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von ClaraSoft:
Ob der auch mit Serilog konfigurierbar ist weiß ich nicht.

Serilog ist ein Sink-Provider, der auch das ILogger-Interface verwendet.
Durch das UseSerilog wird die Factory ausgetauscht, sodass das Logging-Interface selbst das gleiche bleibt aber die Verarbeitungs-Pipeline auf Serilog verändert wird.
Dadurch bleibt aus Entwicker-sicht alles identisch: nur das Ziel wird getauscht.

Die Factory hat aber nichts mit Logger.Log zutun.
Neuer Beitrag 14.01.2021 21:42 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum
Antwort erstellen


© Copyright 2003-2021 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 18.01.2021 02:46