【发布时间】:2013-06-13 03:59:47
【问题描述】:
在我的 LogManager 中,我有一个异步任务,它运行一个 while 循环来将日志信息写入文本文件(并将其添加到集合中)。当我尝试取消这个任务时,循环似乎停止了(我尝试了几个 Console.WriteLines),但是任务没有完成。
下面是这个类的主要方法:
public static DateTime StartTime;
private static CancellationTokenSource SaveLoopToken;
private static Task SaveLoopTask;
public static void Start()
{
LogMessage startMessage = new LogMessage("Logging Started");
startMessage.SetCaller("StartLogging", "LogManager");
StartTime = startMessage.Time;
LogQueue.Post(startMessage);
StartSaveLoop();
}
public static void Stop()
{
LogMessage stopMessage = new LogMessage("Logging Stopped");
stopMessage.SetCaller("StopLogging", "LogManager");
LogQueue.Post(stopMessage);
StopSaveLoop();
}
private static void StartSaveLoop()
{
SaveLoopToken = new CancellationTokenSource();
SaveLoopTask = SaveLoop(SaveLoopToken);
Console.WriteLine("Loop started!");
}
private static void StopSaveLoop()
{
Console.WriteLine("Stop requested");
SaveLoopToken.Cancel();
while (!SaveLoopTask.IsCompleted)
{
Thread.Sleep(100);
}
Console.WriteLine("Loop stopped!");
}
private static void AddLogToCollection(LogMessage logMessage)
{
// Add to MessageList
MessageList.Add(logMessage);
// Add to CurrentMessageList
CurrentMessageList.Add(logMessage);
// Add to FilteredMessageList
if (logMessage.Level >= FilterLevel)
{
FilteredMessageList.Add(logMessage);
}
}
private static async Task SaveLoop(CancellationTokenSource cancel)
{
string logPath = "logs\\";
string logFile = StartTime.ToString("yyyy-MM-dd_HH-mm-ss") + ".log";
string fullPath = Path.Combine(logPath, logFile);
if (!Directory.Exists(logPath))
Directory.CreateDirectory(logPath);
using (FileStream fileStream = new FileStream(fullPath, FileMode.Append, FileAccess.Write, FileShare.Read, 8192, useAsync: true))
{
using (StreamWriter writer = new StreamWriter(fileStream))
{
while (true)
{
LogMessage logMessage = await LogQueue.ReceiveAsync(cancel.Token);
AddLogToCollection(logMessage);
await writer.WriteAsync(String.Format("({0}) ", logMessage.LogID));
await writer.WriteAsync(String.Format("[{0}][{1}] ", logMessage.Time.ToString("HH:mm:ss:fff"), logMessage.Level.ToString()));
await writer.WriteAsync(logMessage.Message);
await writer.WriteLineAsync(String.Format(" ({0} - {1})", logMessage.Method, logMessage.Location));
if (cancel.IsCancellationRequested)
break;
}
}
}
}
以前的 Start/StopSaveLoop 方法:
private static async void StartSaveLoop()
{
SaveLoopToken = new CancellationTokenSource();
Console.WriteLine("Loop started!");
await SaveLoop(SaveLoopToken);
Console.WriteLine("Loop stoped!");
}
private static void StopSaveLoop()
{
Console.WriteLine("Stop requested");
SaveLoopToken.Cancel();
}
【问题讨论】:
-
你可能在睡眠中遇到了死锁。不要混合同步和异步。
-
@SLaks 我已经添加了我以前的方法,因为它们停止工作,我在摆弄它们之前使用了这些方法。但是我从来没有看到“循环停止”的消息。任务状态保持“WaitingForActivation”
-
请不要编写自己的记录器。这是您将遇到的许多心痛中的第一个。这个问题已经解决了。
-
@RyanGates 也许你是对的,但这是我现在遇到的最后一个问题,其他一切正常,所以我会愚蠢地抹去我所有的辛勤工作。另外我不认为这个问题与“记录器相关”,因为我只想知道为什么会发生这种情况,以防我在另一个上下文中需要类似的东西(我可能会)..
-
@RyanGates 我会鼓励每个人在遭受不同的“已构建”解决方案之后使用一个记录器...
标签: c# logging task-parallel-library