Служба не работает Task.run - PullRequest
0 голосов
/ 09 февраля 2020

Я написал windows сервис. Ниже приведены глобальные переменные, определенные внутри класса:

private static TimeSpan pollingInterval;
private static Thread regenerationThread;
private static ManualResetEvent quitThreadEvent;
private static ConcurrentQueue<KeyValuePair<string, string>> queue = new ConcurrentQueue<KeyValuePair<string, string>>();

Вот метод запуска службы:

internal static void Start()
{
    pollingInterval = TimeSpan.FromSeconds(100);
    quitThreadEvent = new ManualResetEvent(false);
    regenerationThread = new Thread(doStart);
    regenerationThread.Start();
}

Вот метод doStart, упомянутый выше:

internal static void doStart()
{   
    queue.Enqueue(new KeyValuePair<string, string>("user1", "password1"));
    queue.Enqueue(new KeyValuePair<string, string>("user2", "password2"));
    queue.Enqueue(new KeyValuePair<string, string>("user3", "password3"));
    while (!quitThreadEvent.WaitOne(pollingInterval))
    {
        // tempList isn't empty, I checked it putting logs here.
        if (tempList.Length != 0)
        {
            var temp = new KeyValuePair<string, string>();
            if (queue.TryDequeue(out temp))
            {
                string username = temp.Key;
                string password = temp.Value;
                // Method comes till here but doesn't execute the statement below and directly reach to end WriteToFile method.
                Task.Run(async () =>
                {
                    await tempFunc(username, password);
                    queue.Enqueue(new KeyValuePair<string, string>(username, password));
                });
            }
        }
        WriteToFile("End of Method");
    }
}

Я не уверен, почему Task.Run не работает. Я поставил логи, но они не показывают никаких ошибок. Я попытался поместить журналы в Task.run, но он не показывает эти журналы. Является ли причиной того, что я запускаю поток, а затем вызываю Task.run внутри него?

Ответы [ 2 ]

1 голос
/ 09 февраля 2020

Я переписал ваш код для использования только асинхронного / ожидающего шаблона.

private static TimeSpan pollingInterval;
private static Task regenerationTask;
private static CancellationTokenSource quitThreadEvent;
private static ConcurrentQueue<KeyValuePair<string, string>> queue = new ConcurrentQueue<KeyValuePair<string, string>>();

internal static void Start()
{
    pollingInterval = TimeSpan.FromSeconds(100);
    quitThreadEvent = new CancellationTokenSource();
    regenerationTask = ExecuteAsync( quitThreadEvent.Token );
}
internal static async Task ExecuteAsync(CancellationToken cancellationToken)
{   
    queue.Enqueue(new KeyValuePair<string, string>("user1", "password1"));
    queue.Enqueue(new KeyValuePair<string, string>("user2", "password2"));
    queue.Enqueue(new KeyValuePair<string, string>("user3", "password3"));
    while ( true )
    {
        await Task.Delay( pollingInterval, cancellationToken ).ConfigureAwait( false );
        // tempList isn't empty, I checked it putting logs here.
        if (tempList.Length != 0)
        {
            var temp = new KeyValuePair<string, string>();
            if (queue.TryDequeue(out temp))
            {
                string username = temp.Key;
                string password = temp.Value;

                // fire and forget task - we do not want to await
                // so we do not need to store the task instance
                _ = WorkWithAsync(username, password);
            }
        }
        WriteToFile("End of Method");
    }
}

private static async Task WorkWithAsync( string username, string password )
{
    await tempfunc( username, password ).ConfigureAwait( false );
    queue.Enqueue(new KeyValuePair<string, string>(username, password));
}

Если вы пропустите метод Stop

internal static void Stop()
{
    quitThreadEvent.Cancel();
    regenerationTask.Wait();
}

internal static async Task StopAsync()
{
    quitThreadEvent.Cancel();
    await regenerationTask;
}
0 голосов
/ 09 февраля 2020

Хотя ваш код не является хорошим способом реализации, как говорят люди, ваш код также должен работать, если только в вашем коде нет ошибок. Я попробовал локально, и это работает. Но 'while (! QuitThreadEvent.WaitOne (pollingInterval))' блокирует выполнение кода внутри для 'pollingInterval' (100 секунд), если вы не установите quitThreadEvent где-либо еще. Убедитесь, что ваша программа не заканчивается до 100 секунд. Если это заканчивается рано, вы можете не увидеть результаты выполнения. И это одна рабочая версия кода:

    internal static void Start()
    {
        pollingInterval = TimeSpan.FromSeconds(1);
        quitThreadEvent = new ManualResetEvent(false);
        regenerationThread = new Thread(doStart);
        regenerationThread.Start();
    }

    internal static void doStart()
    {
        queue.Enqueue(new KeyValuePair<string, string>("user1", "password1"));
        queue.Enqueue(new KeyValuePair<string, string>("user2", "password2"));
        queue.Enqueue(new KeyValuePair<string, string>("user3", "password3"));
        while (!quitThreadEvent.WaitOne(pollingInterval))
        {
            // tempList isn't empty, I checked it putting logs here.
            if (true)
            {
                var temp = new KeyValuePair<string, string>();
                if (queue.TryDequeue(out temp))
                {
                    string username = temp.Key;
                    string password = temp.Value;
                    // Method comes till here but doesn't execute the statement below and directly reach to end WriteToFile method.
                    Task.Run(async () =>
                    {
                        await tempFunc(username, password);
                        queue.Enqueue(new KeyValuePair<string, string>(username, password));
                    });
                }
                Console.WriteLine("End of the method.");
                break;
            }
        }
    }

    internal static async Task tempFunc(string userName, string pwd)
    {
        Console.WriteLine($"UserName = {userName}, Pwd = {pwd}");
        await Task.Delay(1000);
    }

    static void Main(string[] args)
    {
        Start();
        Thread.Sleep(5000);
    }

`

...