- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我目前已经在旧 View 中编写了一个简单的事件记录器Backgroundworker
类(class)。我正在尝试将其转换为 TPL 实现。
我对 C# 中的线程的使用还不够多,所以我更喜欢其中一个,但我知道 TPL 越来越受欢迎,我想尽可能多地坚持使用它。另一个原因是,使用当前代码,我找不到制作 EventLog
的简单方法。类线程安全。我发现自己在使用 BeginInvoke
从非 UI 线程写入日志,这对我来说似乎很困惑。
所以这是原始代码。
public class EventLog
{
public String LogPath { get; set; }
public List<LogEvent> Events { get; private set; }
public static EventLog Instance { get { return lazyInstance.Value; } }
private static readonly Lazy<EventLog> lazyInstance = new Lazy<EventLog>(() => new EventLog());
private EventLog()
{
Events = new List<LogEvent>();
LogPath = Assembly.GetExecutingAssembly().CodeBase;
LogPath = Path.GetDirectoryName(LogPath);
LogPath = LogPath.Replace("file:\\", "");
LogPath = LogPath + "\\Log.txt";
}
public override void publish(LogEvent newEvent)
{
Events.Add(newEvent);
if (!LogEventWriter.Instance.IsBusy)
LogEventWriter.Instance.RunWorkerAsync(LogPath);
LogEventWriter.Instance.LogEvents.Add(newEvent);
}
}
internal class LogEventWriter : BackgroundWorker
{
public BlockingCollection<LogEvent> LogEvents { get; set; }
public static LogEventWriter Instance { get { return lazyInstance.Value; } }
private static readonly Lazy<LogEventWriter> lazyInstance = new Lazy<LogEventWriter>(() => new LogEventWriter());
private LogEventWriter()
{
WorkerSupportsCancellation = true;
LogEvents = new BlockingCollection<LogEvent>();
}
protected override void OnDoWork(DoWorkEventArgs e)
{
if (e.Argument != null && e.Argument is String)
{
String logPath = (String)e.Argument;
using (StreamWriter logFile = new StreamWriter(logPath, true))
{
while (!CancellationPending)
{
LogEvent anEvent = LogEvents.Take();
logFile.WriteLine(anEvent.Message);
logFile.Flush();
if (anEvent.Message.Contains("Application Terminated"))
break;
}
logFile.Close();
}
}
e.Cancel = true;
}
}
我目前对日志的思路是在系统出现故障时尽快将日志写入文件,这样日志就会有尽可能多的信息。这就是Backgroundworker
是为了。我也只保留一个 List<LogEvent>
在EventLog
类,以便用户可以在当前日志中搜索特定事件(未完全实现/完善)。
这是我当前的 TPL 解决方案。我已尽我所能将日志记录功能包装到 Task
中s 但我仍然觉得我应该有一个类似于 publish
的函数而不必直接放置 LogEvent
进入 BlockingCollection<>
这样我就可以在主 UI 的单独线程上运行日志记录。
还有更简洁的方法来停止 Task
无需发送“特殊”LogEvent
给他们break
来自他们的循环?
public class EventLog
{
public static EventLog Instance { get { return lazyInstance.Value; } }
private static readonly Lazy<EventLog> lazyInstance = new Lazy<EventLog>(() => new EventLog());
public String LogPath { get; set; }
public ConcurrentQueue<LogEvent> Events { get; set; }
private EventLog()
{
Events = new ConcurrentQueue<LogEvent>();
WriteQueue = new BlockingCollection<LogEvent>();
LogEventQueue = new BlockingCollection<LogEvent>();
LogPath = Assembly.GetExecutingAssembly().CodeBase;
LogPath = Path.GetDirectoryName(LogPath);
LogPath = LogPath.Replace("file:\\", "");
LogPath = LogPath + "\\LogASDF.txt";
StartManager();
StartWriter();
}
public BlockingCollection<LogEvent> LogEventQueue { get; set; }
private void StartManager()
{
var writeTask = Task.Factory.StartNew(() =>
{
while (true)
{
LogEvent anEvent = LogEventQueue.Take();
Events.Enqueue(anEvent);
WriteQueue.Add(anEvent);
if (anEvent.Message.Contains("Application Terminated"))
break;
}
});
}
private BlockingCollection<LogEvent> WriteQueue { get; set; }
private void StartWriter()
{
var writeTask = Task.Factory.StartNew(() =>
{
using (StreamWriter logFile = new StreamWriter(LogPath, true))
{
while(true)
{
LogEvent anEvent = WriteQueue.Take();
logFile.WriteLine(anEvent.Message);
logFile.Flush();
if (anEvent.Message.Contains("Application Terminated"))
break;
}
logFile.Close();
}
});
}
}
CancellationToken
取消这两个任务?我不明白如果 BlockingCollection
正在阻塞,我总是必须“脉冲”集合以使其解除阻塞。LogEvent
进入日志,而不必直接将其插入 LogEventQueue
?最佳答案
现在您的代码不是 thread-safe
因为你有这个:
public List<LogEvent> Events { get; private set; }
List<T>
不是线程安全的,可以从外部代码更改。而且我根本看不出它是否被使用过。
另外,你真的应该使用 CancellationToken
在你的代码中因为在其他情况下你会遇到麻烦:例如,你有 5 条消息在队列中,你决定取消你的工作。在这种情况下,检查 Shutdown Log
只会在一段时间后中断循环,这会让您的类(class)的最终用户感到困惑。
此外, BlockingCollection<T>.Take
也有过载使用 CancellationToken
的方法, 但在取消的情况下你会得到 OperationCanceledException
:
try
{
LogEvent anEvent = WriteQueue.Take(CancellationPending);
}
catch (OperationCanceledException ex)
{
// handle stop here;
}
死循环在多线程中是非常糟糕的做法,我建议不要使用它。
关于c# - 从 BackgroundWorker 转向日志类的 TPL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32230071/
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
如何让我的节点始终朝着它所面对的方向前进? float tilt = _motionManager.accelerometerData.acceleration.x; [_player runActi
我继承了一个基于 Java、基于 Web 的 7 年前的产品,其中包含大约 75 万行代码。正如预期的那样,考虑到它的年龄,它不是基于 Maven 的结构,. Maven 用于构建和发布应用程序。但是
既然新版本的 eclipse 已经发布了,我应该立即转向吗?如果我的插件在 Galileo 中工作,它也能在 indigo 中工作吗? 最佳答案 如果不尝试或研究特定插件提供商关于 Indigo 兼容
我有一个使用 html、css 和 jQuery 制作的静态应用程序。我现在将其导入到 Angular 2 中,但遇到了日期问题: // GET DATE let d = new Date(); le
我在 C# 中为我的 unity 项目创建了一个植绒算法。我试着关注 this example ,但问题是把所有东西放在一起,我无法推断。以下代码是我希望拥有一个领导者跟随植绒系统的一部分。 我在基本
我有一张这样的 table Index | FeatureType | FeatureExists 1 | BR | 0 1 | EI
我有一个拥有大约 60,000 名付费客户的网站,其中 3000 名使用 Windows XP + IE 8。我想要一个可以为我的所有客户提供服务的证书(或多证书解决方案)。问题是 SHA-1 已被弃
我正在尝试找出如何以不同的方式执行我的 JavaScript 回调。 我目前的回调风格,将回调传递给函数,函数调用回调。例如: 函数调用 doSomething(function(data){
我有一个适用于 Android 2.1 的应用程序,我想为 Android 2.2+ 的设备添加移动到 SD 的支持。 我添加了代码: 但是如果我让我的项目保持在sdk level 7以上,我会出
此代码附在相机上: transform.position += Input.GetAxis("Vertical") * transform.forward * mod; transform.posit
jQuery 是 javaScript 的框架。但是,我能够很好地使用 javaScript 进行编码。我不知道如何在 jQuery 中(重新)编码它! 从头开始学习 jQuery 是唯一的方法还是我
我将一些旧代码从另一个库移至 jQuery,并在此过程中破坏了一些其他代码。我认为 jQuery 实现其 .html 函数的方式让我很伤心。 以下部分是使用以下语法通过 AJAX 调用和成功函数生成的
我在网上搜索了一些不错的代码,突然间我碰到了一个,但是它已经在 Eclipse 中工作了,因为我没有 Eclipse(而且我也不打算安装它)我可以在我的 VS10 上正确编译它。问题是所有链接器引用都
我是 Scrum 团队的一名测试人员,试图自动化我们的测试回归集。 我们的前端是用 Java Angular 开发的,我们使用 Tosca 测试套件来自动化我们的测试集。我遇到的问题如下: 使用 To
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 8 年前。 Improve this qu
SVG 图标与字体图标相比有一些优势:它们可以缩放以适应可变大小的容器元素,并且理论上您可以更改各个路径的颜色。我也喜欢我可以在 Inkscape 中轻松制作它们的事实:P 但我如何在 CSS 文件中
关于将 iOS 应用程序迁移到 Swift 3.0 的过程。我终于摆脱了(所有)语法错误。 不过,我似乎还有一个很大的问题。 以下是我在构建项目时在 Xcode 中得到的最终错误消息: 这里太长了,所
自从我开始编码以来,我就是一名 .NET 开发人员。我想学习 Win32 编程。需要关于从哪里开始的建议。学习 Win32 编程的最佳资源/书籍是什么。我知道一点“大学 C++”。 最佳答案 毫无疑问
在windows上用了10多年,如何迁移到*nix平台?哪种口味更容易处理,让我更舒服,然后也许我可以切换到更标准的 *nix 口味?我已经推迟了一段时间了。帮助我进行额外的推送。 最佳答案 Linu
我是一名优秀的程序员,十分优秀!