简体   繁体   中英

SynchronizationContext is null in OnStart method of WindowsService

I am trying to create a background Task for my windows service (it is already installed via InstallUtil.exe) and use SynchronizationContext to send some messages to the main Service thread.

Unfortunately SynchronizationContext.Current is always null on service start.

I've saw some questions around the topic and hints on why SynchronizationContext is null in various scenarios (eg in Winforms, WPF apps) but no clue about the Windows services.

How can I resolve this issue? Below the code:

using Lextm.SharpSnmpLib.Messaging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SnmpTrapListenerService
{
    public partial class SnmpTrapListenerService : ServiceBase
    {
        public Listener Listener { get; set; }
        public CancellationTokenSource CancellationTokenSource { get; set; }
        public Task PulseTask { get; set; }
        public SynchronizationContext SyncContext { get; set; }

        public SnmpTrapListenerService()
        {
            //Debugging windows service.  
            Debugger.Launch();
            InitializeComponent();
            Debug.WriteLine($"Main service threadId: {Thread.CurrentThread.ManagedThreadId}");
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                CancellationTokenSource = new CancellationTokenSource();
                SyncContext = SynchronizationContext.Current; //Here I'm getting always null.
                PulseTask = new Task(x =>
                {
                    Debug.WriteLine($"Pulse task threadId: {Thread.CurrentThread.ManagedThreadId}");
                    while (true)
                    {
                        var context = (SynchronizationContext)x;
                        context.Post(new SendOrPostCallback(y => DoSomethingOnServiceMainThread()), null);
                        Debug.WriteLine($"Alive at {DateTime.Now.ToLongTimeString()}");
                        Thread.Sleep(5000);
                    }
                }, SyncContext, CancellationTokenSource.Token);

                PulseTask.Start();

                Listener = new Listener();
                Listener.AddBinding(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 162)); //IP address of listener system  
                Listener.MessageReceived += Listener_MessageReceived;
                Listener.StartAsync();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            Debug.WriteLine("Service started");
        }
        private static void Listener_MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            File.AppendAllText("servicelog.log", "Version :" + e.Message.Version + "\n");
            File.AppendAllText("servicelog.log", "Version :" + e.Message.Scope.Pdu.Variables[4].Data.ToString() + "\n");
        }

        protected override void OnStop()
        {
            CancellationTokenSource.Cancel();
            Listener.Stop();
            Debug.WriteLine("Service stopped");
        }

        private void DoSomethingOnServiceMainThread() 
        {
            //Some work that needs to be done one Service main thread.
        }
    }
}

Console and Service applications do not have a default SynchronizationContext. This is because there is no "UI" thread that is pumping messages constantly while the application runs.

The question is why do you need a synchronization context?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM