SynchronizationContext является нулевым в методе OnStart WindowsService - PullRequest
0 голосов
/ 04 апреля 2019

Я пытаюсь создать фоновую задачу для моей службы Windows (она уже установлена ​​через InstallUtil.exe) и использую SynchronizationContext для отправки некоторых сообщений в основной поток службы.

К сожалению, SynchronizationContext.Current всегда null при запуске службы.

Я видел несколько вопросов по этой теме и подсказки о том, почему SynchronizationContext имеет значение null в различных сценариях (например, в Winforms, приложениях WPF), но не имею представления о службах Windows.

Как я могу решить эту проблему? Ниже код:

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.
        }
    }
}

1 Ответ

1 голос
/ 04 апреля 2019

Консольные и служебные приложения не имеют SynchronizationContext по умолчанию.Это связано с тем, что нет потока «UI», который постоянно качает сообщения во время работы приложения.

Вопрос в том, зачем вам нужен контекст синхронизации?

...