我已经编写了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个步骤:
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);
}
}
我已将您的代码重写为仅使用异步/等待模式。
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;
}
尽管您的代码不是人们所说的一种很好的实现方式,但是您的代码也应该可以工作,除非您的代码在其他地方出了问题。我在本地尝试过,并且有效。但是,“ 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);
}
`