Nursery是一个简单的进程托管Demo,用于启动console应用程序。
问题
CheckBoxList
这里一开始用的是ObservableCollection的方式,后感感觉太过于繁杂,改为直接向ListBox中添加CheckBox:ProcessListBox.Items.Add(checkBox);。
ListView的动态更新
或许有用的资料 1. CheckBoxList(ObservableCollection)in WPF 2. WPF ListView实时更新及INotifyPropertyChanged使用演示 3. WPF Listview绑定数据发生改变后前端没有更新
尝试
这里想的是另起一个监控线程,对线程的实时信息进行更新。对infoList更新后,通过ProcessInformationListView.ItemsSource = infoList;使其生效,但是遇到了线程间对对象访问的问题:
System.InvalidOperationException:“调用线程无法访问此对象,因为另一个线程拥有该对象。
ProcessInformationListView.Dispatcher.BeginInvoke(new Action(() => |
ListView 的内容并不会更改。不仅如此,monitor执行后主线程不能向ListView中添加内容了,如果先添加了内容,monitor执行后内容不会改变。
最终解决方式
LIstView的数据源使用ObservableCollection:private ObservableCollection<ProcessInformation> InfoList { get; set; }- 实体类
ProcessInformation继承INotifyPropertyChanged接口public class ProcessInformation : INotifyPropertyChanged
{
private string _Process;
private int _PID;
private string _CPU;
private string _Memory;
public event PropertyChangedEventHandler PropertyChanged;
public string Process {
get { return _Process; }
set { _Process = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Process"));
}
}
public int PID {
get { return _PID; }
set { _PID = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PID"));
}
}
public string CPU {
get { return _CPU; }
set { _CPU = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CPU"));
}
}
public string Memory {
get { return _Memory; }
set { _Memory = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Memory"));
}
}
} - 跨线程访问(这个就不用了,因为
ObservableCollection实现了INotifyPropertyChanged接口,当InfoList发生改变时会自动更新ListView,不用手动更新ListView.ItemsSource,也就不会发生跨线程访问ListView了。ps: 好像是跨线程更改前台的数据才会出现这个问题) 不更新、不能添加GridView的原因也应该是没有实现INotifyPropertyChanged接口
ProcessInformationListView.Dispatcher.BeginInvoke(new Action(() => |
不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改
private ObservableCollection<ProcessInformation> infoList { get; set; } |
System.NotSupportedException:“该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。”
ObservableCollection类型的CollectionView不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。(我也不懂是哪个线程对该对象进行了访问,不是我的监控线程)
解决方式:
ThreadPool.QueueUserWorkItem(delegate |
NotifyIcon
程序托盘图标用的是HandyControl的控件。 根据文档编辑图标、绑定事件即可。
<hc:NotifyIcon x:Name="NotifyIcon" Text="ProcessNursery" |
NLog的日志系统,主要是调试时候找问题的。
分为以下几种日志等级:
Trace
Debug
Info
Warn
Error
Fatal
配置
NLog使用需要添加配置文件,可以添加到App.config,也可以新建NLog.config然后添加内容。我手动新建配置文件之后使用不了,使用NuGet命令添加成功。(工具->NuGet 包管理器->程序包管理器控制台,输入Install-Package NLog.Config [-Version 4.7.5])。关于自定义日志,可以看这里
|
使用
private static Logger logger = LogManager.GetCurrentClassLogger(); |
进程的CPU与内存
使用.Net的PerformanceCounter类型对进程的性能进行监控
Process process = pNersury[fileName].process; |
实时获取子进程的输出
参考: 1. 启动一个进程并实时获取状态信息 2. c# - 从Process获取实时输出
UseShellExecute必须为false,不然无法在代码中读标准。 RedirectStandardOutput必须为true,这样我们才能在代码中访问标准流。 EnableRaisingEvents必须为true,这样才会引发OutputDataReceived和Exited
解决方式是两条内容的结合:
Process child = new Process(); |