我有一个奇怪的问题:
在我的C#应用程序中,我正在创建另一个线程,如下所示:
Thread printThread = new Thread(printWorker);
printThread.Name = "Logger MainThread";
printThread.IsBackground = true;
printThread.Start();
当我的主线程完成时,这个新线程会继续工作,虽然它被标记为背景。
造成这种情况的原因是什么? 这个对象持有Mutex对象,不确定这可能是原因......
任何想法?
以下是printWorker方法的代码:
while (loggerIsActive)
{
LogMessage log = LoggerQueue.Dequeue();
if (log.message != null)
{
syncLogObj.WaitOne();
lock (writerobj)
{
StreamWriter sw;
if (!File.Exists(fName))
{
sw = File.CreateText(fName);
}
else
{
sw = new StreamWriter(fName, true);
}
using (sw)
{
if (log.message != "")
{
if (log.message.EndsWith("\r\n"))
{
log.message =
log.message.Substring(0, log.message.Length - 2);
}
sw.WriteLine(string.Format("[{0}][{3}][{1}] | {2}",
log.msgTime,
log.level.ToString(),
log.message,
log.sender.ToString()));
}
sw.Flush();
sw.Close();
}
}
syncLogObj.ReleaseMutex();
}
Thread.Sleep(5);
}
答案 0 :(得分:12)
试试这个:
通过VS启动应用并正常退出。如您所述,VS应保持在调试模式。单击暂停按钮(全部中断),然后转到Debug-> Windows-> Threads。你在列表中看到了“Logger MainThread”吗?
否则,有了这些问题,通过System.Diagnostics.Debug.Print语句监视程序状态总是有用的(你可以看到它们在VS输出窗口中打印)。
答案 1 :(得分:7)
不漂亮。但这不是电视。请继续阅读:
1)不确定你是否正在使用它,但看起来你应该在排队(主pgm)或出队(线程)之前锁定loggerqueue。
2)无需仅使用此设置锁定writerobj。但实际上你应该这样做,你可以安全地杀死线程不是在写:
如果您正确执行此操作,则不必使用Waits和互斥锁。无论如何,如果你正在使用等待,你将不需要睡眠。
此应用程序的一般建议:为什么不登录主线程?如果您的日志记录繁忙,则日志结果将毫无用处。
但是在极少数情况下这可能是错误的。 Entonces ......
使线程能够很好地解决这个问题的一般建议:
答案 2 :(得分:4)
你有很多事情发生,你显然没有表现出来......
例如:您有syncLogObj.WaitOne();
,但我们没有看到宣布syncLogObj
的位置,或者在您的计划中的其他位置使用过。
另外,你不需要它......完全摆脱syncLogObj
的东西(包括“ReleaseMutex”垃圾)......你已经有了一个锁(blah){},这就是全部你需要(从你显示的代码)。
主线程很可能没有结束,可能是因为这个或其他一些对象让它保持打开状态。
syncLogObj
(因为你已经拥有“锁定”)loggerIsActive = false
。 从我看到的内容 - 您根本不需要lock (writerobj)
,因为(我很确定),您似乎只有一个帖子即写入日志。
只有当你有两个或更多个线程运行该代码时(基本上)才会出现“锁定”。
答案 3 :(得分:3)
如果在你的主线程完成之前printworker
没有完成,那么main将会死掉,你的printworker
线程将被操作系统杀死。如果您希望main等待您创建的主题,那么您应该在main中调用printThread.Join()
。那将是主要的等待你的线程。
当主程序完成后你的程序会死掉,你的printThread
将被操作系统销毁,它将无法继续运行。
来自here
后台线程与之相同 前台线程有一个例外: 后台线程不保留 托管执行环境正在运行 一旦所有前景线程都已存在 在托管过程中停止(其中 .exe文件是托管程序集), 系统停止所有背景 线程并关闭。
答案 4 :(得分:2)
Tony the Tiger有正确的想法,但在应用程序关闭之前需要添加额外的代码来杀死线程。
printThread.Join(1000);
if(printThread!=null && printThread.IsAlive)
printThread.Abort();
答案 5 :(得分:1)
Thread.Abort();
Thread.Dispose();
如果我没弄错的话应该这样做。