服务未运行Task.run

问题描述 投票:0回答:3

我已经编写了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的原因吗?

c# multithreading windows-services
3个回答
0
投票

您可以执行以下2个步骤:

  • 使用异步等待代码标记
  • Void()转换为Task
  • 这样调用:await DoStart();

internal async Task 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.


                await tempFunc(username, password);
                queue.Enqueue(new KeyValuePair<string, string>(username, password));

            }
        }
        WriteToFile("End of Method);
    }
}


0
投票

我已将您的代码重写为仅使用异步/等待模式。

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
投票

尽管您的代码不是人们所说的一种很好的实现方式,但是您的代码也应该可以工作,除非您的代码在其他地方出了问题。我在本地尝试过,并且有效。但是,“ 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);
    }

`

© www.soinside.com 2019 - 2024. All rights reserved.