Mercurial > pub > ImplabNet
changeset 47:b181f7bcb259 interactive logger
refactoring, interactive tarce log almost complete
author | cin |
---|---|
date | Thu, 17 Apr 2014 18:49:36 +0400 |
parents | 9ce97b262a7a |
children | d9d794b61bb9 |
files | Implab.Diagnostics.Interactive/Implab.Diagnostics.Interactive.csproj Implab.Diagnostics.Interactive/InteractiveListener.cs Implab.Diagnostics.Interactive/InteractiveTracer.cs Implab.Diagnostics.Interactive/Properties/DataSources/TraceViewItem.datasource Implab.Diagnostics.Interactive/TraceForm.Designer.cs Implab.Diagnostics.Interactive/TraceForm.cs Implab.Diagnostics.Interactive/TraceForm.resx Implab.Diagnostics.Interactive/TraceViewControl.Designer.cs Implab.Diagnostics.Interactive/TraceViewControl.cs Implab.Diagnostics.Interactive/TraceViewControl.resx Implab.Diagnostics.Interactive/TraceViewItem.cs Implab/Diagnostics/TextFileListener.cs Implab/Diagnostics/TextListenerBase.cs |
diffstat | 13 files changed, 265 insertions(+), 296 deletions(-) [+] |
line wrap: on
line diff
--- a/Implab.Diagnostics.Interactive/Implab.Diagnostics.Interactive.csproj Thu Apr 17 08:49:24 2014 +0400 +++ b/Implab.Diagnostics.Interactive/Implab.Diagnostics.Interactive.csproj Thu Apr 17 18:49:36 2014 +0400 @@ -41,7 +41,7 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> - <Compile Include="InteractiveTracer.cs" /> + <Compile Include="InteractiveListener.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="TextStyle.cs" /> <Compile Include="TraceForm.cs"> @@ -50,16 +50,10 @@ <Compile Include="TraceForm.Designer.cs"> <DependentUpon>TraceForm.cs</DependentUpon> </Compile> - <Compile Include="TraceViewControl.cs"> - <SubType>UserControl</SubType> - </Compile> - <Compile Include="TraceViewControl.Designer.cs"> - <DependentUpon>TraceViewControl.cs</DependentUpon> - </Compile> <Compile Include="TraceViewItem.cs" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\external\Implab\Implab.csproj"> + <ProjectReference Include="..\Implab\Implab.csproj"> <Project>{f550f1f8-8746-4ad0-9614-855f4c4b7f05}</Project> <Name>Implab</Name> </ProjectReference> @@ -68,9 +62,9 @@ <EmbeddedResource Include="TraceForm.resx"> <DependentUpon>TraceForm.cs</DependentUpon> </EmbeddedResource> - <EmbeddedResource Include="TraceViewControl.resx"> - <DependentUpon>TraceViewControl.cs</DependentUpon> - </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Properties\DataSources\TraceViewItem.datasource" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab.Diagnostics.Interactive/InteractiveListener.cs Thu Apr 17 18:49:36 2014 +0400 @@ -0,0 +1,107 @@ +using Implab.Parallels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Implab.Diagnostics.Interactive +{ + public class InteractiveListener: Disposable + { + TraceForm m_form; + + SynchronizationContext m_syncGuiThread; + + readonly IPromiseBase m_guiFinished; + readonly Promise<object> m_guiStarted = new Promise<object>(); + + readonly IPromiseBase m_workerFinished = new Promise<object>(); + + readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>(); + readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false); + + int m_queueLength; + bool m_exitPending; + + readonly object m_pauseLock = new object(); + bool m_paused; + readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true); + + public InteractiveListener() { + m_guiFinished = AsyncPool.InvokeNewThread(() => { + GuiThread(); + return 0; + }); + + m_guiStarted.Join(); + } + + void GuiThread() { + m_form = new TraceForm(); // will create SynchronizationContext + m_syncGuiThread = SynchronizationContext.Current; + m_guiStarted.Resolve(); + Application.Run(); + } + + void QueueThread() { + while (!m_exitPending) { + if (m_paused) + m_pauseEvent.WaitOne(); + + TraceViewItem item; + if (m_queue.TryDequeue(out item)) { + Interlocked.Decrement(ref m_queueLength); + + m_syncGuiThread.Send(x => m_form.AddTraceEvent(item),null); + } else { + m_queueEvent.WaitOne(); + } + } + } + + public void Pause() { + // for consistency we need to set this properties atomically + lock (m_pauseLock) { + m_pauseEvent.Reset(); + m_paused = true; + } + } + + public void Resume() { + // for consistency we need to set this properties atomically + lock (m_pauseLock) { + m_paused = false; + m_pauseEvent.Set(); + } + } + + void Enqueue(TraceViewItem item) { + m_queue.Enqueue(item); + if (Interlocked.Increment(ref m_queueLength) == 1) + m_queueEvent.Set(); + } + + public void ShowForm() { + m_syncGuiThread.Post(x => m_form.Show(), null); + } + + public void HideForm() { + m_syncGuiThread.Post(x => m_form.Hide(), null); + } + + void Terminate() { + m_syncGuiThread.Post(x => Application.ExitThread(), null); + } + + protected override void Dispose(bool disposing) { + if (disposing) { + Terminate(); + m_guiFinished.Join(); + } + base.Dispose(disposing); + } + } +}
--- a/Implab.Diagnostics.Interactive/InteractiveTracer.cs Thu Apr 17 08:49:24 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -using Implab.Parallels; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace Implab.Diagnostics.Interactive -{ - public class InteractiveTracer: Disposable - { - TraceForm m_form; - SynchronizationContext m_syncGuiThread; - readonly IPromiseBase m_completed; - readonly Promise<object> m_started = new Promise<object>(); - - public InteractiveTracer() { - m_completed = AsyncPool.InvokeNewThread(() => { - GuiThread(); - return 0; - }); - - m_started.Join(); - } - - void GuiThread() { - m_form = new TraceForm(); // will create SynchronizationContext - m_syncGuiThread = SynchronizationContext.Current; - m_started.Resolve(); - Application.Run(); - } - - public void ShowForm() { - m_syncGuiThread.Post(x => m_form.Show(), null); - } - - public void HideForm() { - m_syncGuiThread.Post(x => m_form.Hide(), null); - } - - void Terminate() { - m_syncGuiThread.Post(x => Application.ExitThread(), null); - } - - protected override void Dispose(bool disposing) { - if (disposing) { - Terminate(); - m_completed.Join(); - } - base.Dispose(disposing); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab.Diagnostics.Interactive/Properties/DataSources/TraceViewItem.datasource Thu Apr 17 18:49:36 2014 +0400 @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + This file is automatically generated by Visual Studio .Net. It is + used to store generic object data source configuration information. + Renaming the file extension or editing the content of this file may + cause the file to be unrecognizable by the program. +--> +<GenericObjectDataSource DisplayName="TraceViewItem" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource"> + <TypeInfo>Implab.Diagnostics.Interactive.TraceViewItem, Implab.Diagnostics.Interactive</TypeInfo> +</GenericObjectDataSource> \ No newline at end of file
--- a/Implab.Diagnostics.Interactive/TraceForm.Designer.cs Thu Apr 17 08:49:24 2014 +0400 +++ b/Implab.Diagnostics.Interactive/TraceForm.Designer.cs Thu Apr 17 18:49:36 2014 +0400 @@ -23,30 +23,100 @@ /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { - this.traceViewControl1 = new Implab.Diagnostics.Interactive.TraceViewControl(); + this.components = new System.ComponentModel.Container(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); + this.eventsDataGrid = new System.Windows.Forms.DataGridView(); + this.traceViewItemBindingSource = new System.Windows.Forms.BindingSource(this.components); + this.threadDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.messageDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).BeginInit(); this.SuspendLayout(); // - // traceViewControl1 + // eventsDataGrid // - this.traceViewControl1.Location = new System.Drawing.Point(13, 13); - this.traceViewControl1.Name = "traceViewControl1"; - this.traceViewControl1.Size = new System.Drawing.Size(267, 248); - this.traceViewControl1.TabIndex = 0; + this.eventsDataGrid.AllowUserToAddRows = false; + this.eventsDataGrid.AllowUserToDeleteRows = false; + this.eventsDataGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.eventsDataGrid.AutoGenerateColumns = false; + this.eventsDataGrid.BackgroundColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + dataGridViewCellStyle1.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this.eventsDataGrid.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; + this.eventsDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.eventsDataGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.threadDataGridViewTextBoxColumn, + this.messageDataGridViewTextBoxColumn}); + this.eventsDataGrid.DataSource = this.traceViewItemBindingSource; + dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle3.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this.eventsDataGrid.DefaultCellStyle = dataGridViewCellStyle3; + this.eventsDataGrid.Location = new System.Drawing.Point(12, 12); + this.eventsDataGrid.Name = "eventsDataGrid"; + this.eventsDataGrid.ReadOnly = true; + this.eventsDataGrid.RowHeadersWidth = 17; + this.eventsDataGrid.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.eventsDataGrid.Size = new System.Drawing.Size(939, 480); + this.eventsDataGrid.TabIndex = 1; + this.eventsDataGrid.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.eventsDataGrid_CellFormatting); + // + // traceViewItemBindingSource + // + this.traceViewItemBindingSource.DataSource = typeof(Implab.Diagnostics.Interactive.TraceViewItem); + // + // threadDataGridViewTextBoxColumn + // + this.threadDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader; + this.threadDataGridViewTextBoxColumn.DataPropertyName = "Thread"; + this.threadDataGridViewTextBoxColumn.HeaderText = "TID"; + this.threadDataGridViewTextBoxColumn.Name = "threadDataGridViewTextBoxColumn"; + this.threadDataGridViewTextBoxColumn.ReadOnly = true; + this.threadDataGridViewTextBoxColumn.Width = 5; + // + // messageDataGridViewTextBoxColumn + // + this.messageDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.messageDataGridViewTextBoxColumn.DataPropertyName = "FormattedMessage"; + dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this.messageDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle2; + this.messageDataGridViewTextBoxColumn.HeaderText = "Message"; + this.messageDataGridViewTextBoxColumn.Name = "messageDataGridViewTextBoxColumn"; + this.messageDataGridViewTextBoxColumn.ReadOnly = true; // // TraceForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(292, 273); - this.Controls.Add(this.traceViewControl1); + this.ClientSize = new System.Drawing.Size(963, 504); + this.Controls.Add(this.eventsDataGrid); this.Name = "TraceForm"; this.Text = "TraceForm"; + ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).EndInit(); this.ResumeLayout(false); } #endregion - private TraceViewControl traceViewControl1; + private System.Windows.Forms.DataGridView eventsDataGrid; + private System.Windows.Forms.BindingSource traceViewItemBindingSource; + private System.Windows.Forms.DataGridViewTextBoxColumn threadDataGridViewTextBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn messageDataGridViewTextBoxColumn; + } } \ No newline at end of file
--- a/Implab.Diagnostics.Interactive/TraceForm.cs Thu Apr 17 08:49:24 2014 +0400 +++ b/Implab.Diagnostics.Interactive/TraceForm.cs Thu Apr 17 18:49:36 2014 +0400 @@ -10,8 +10,12 @@ namespace Implab.Diagnostics.Interactive { public partial class TraceForm : Form { + readonly Dictionary<int, Color> m_threadColors = new Dictionary<int,Color>(); + readonly Random m_rand = new Random(); + public TraceForm() { InitializeComponent(); + } protected override void OnFormClosing(FormClosingEventArgs e) { @@ -21,5 +25,34 @@ Hide(); } } + + public void AddTraceEvent(int indent, int thread, string message) { + traceViewItemBindingSource.Add(new TraceViewItem { + Indent = indent, + Thread = thread, + Message = message, + Timestamp = Environment.TickCount + }); + + } + + public void AddTraceEvent(TraceViewItem item) { + traceViewItemBindingSource.Add(item); + } + + Color GetThreadColor(int thread) { + Color result; + if (!m_threadColors.TryGetValue(thread, out result)) { + result = Color.FromArgb(m_rand.Next(4)*64, m_rand.Next(4)*64, m_rand.Next(4)*64); + m_threadColors[thread] = result; + } + return result; + } + + private void eventsDataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { + var data = (TraceViewItem)traceViewItemBindingSource[e.RowIndex]; + e.CellStyle.Padding = new Padding(data.Indent * 10,0,0,0); + e.CellStyle.ForeColor = GetThreadColor(data.Thread); + } } }
--- a/Implab.Diagnostics.Interactive/TraceForm.resx Thu Apr 17 08:49:24 2014 +0400 +++ b/Implab.Diagnostics.Interactive/TraceForm.resx Thu Apr 17 18:49:36 2014 +0400 @@ -117,4 +117,7 @@ <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> + <metadata name="traceViewItemBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> </root> \ No newline at end of file
--- a/Implab.Diagnostics.Interactive/TraceViewControl.Designer.cs Thu Apr 17 08:49:24 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -namespace Implab.Diagnostics.Interactive { - partial class TraceViewControl { - /// <summary> - /// Required designer variable. - /// </summary> - private System.ComponentModel.IContainer components = null; - - /// <summary> - /// Clean up any resources being used. - /// </summary> - /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> - protected override void Dispose(bool disposing) { - if (disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// <summary> - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// </summary> - private void InitializeComponent() { - this.SuspendLayout(); - // - // TraceViewControl - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.SystemColors.Window; - this.Name = "TraceViewControl"; - this.ResumeLayout(false); - - } - - #endregion - } -}
--- a/Implab.Diagnostics.Interactive/TraceViewControl.cs Thu Apr 17 08:49:24 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace Implab.Diagnostics.Interactive { - public partial class TraceViewControl : UserControl { - int m_maxEvents = 1000; - - string m_status = "ready"; - - readonly LinkedList<TraceViewItem> m_events = new LinkedList<TraceViewItem>(); - public TraceViewControl() { - InitializeComponent(); - - var ticks = Environment.TickCount; - - for (int i = 0; i < 1333; i++) { - AddViewItem(new TraceViewItem { - indent = i % 4, - message = String.Format("Auto generated {0}", i), - thread = 2, - timestamp = ticks + i*10 - }); - } - } - - public void AddViewItem(TraceViewItem item) { - m_events.AddLast(item); - if (m_events.Count > m_maxEvents) - m_events.RemoveFirst(); - } - - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - - if (m_status != null) - e.Graphics.DrawString(m_status, DefaultFont, Brushes.Black, 0, 0); - - } - - protected override void OnMouseMove(MouseEventArgs e) { - base.OnMouseMove(e); - - m_status = String.Format("({0},{1})", e.X, e.Y); - Invalidate(); - } - - } -}
--- a/Implab.Diagnostics.Interactive/TraceViewControl.resx Thu Apr 17 08:49:24 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<root> - <!-- - Microsoft ResX Schema - - Version 2.0 - - The primary goals of this format is to allow a simple XML format - that is mostly human readable. The generation and parsing of the - various data types are done through the TypeConverter classes - associated with the data types. - - Example: - - ... ado.net/XML headers & schema ... - <resheader name="resmimetype">text/microsoft-resx</resheader> - <resheader name="version">2.0</resheader> - <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> - <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> - <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> - <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> - <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> - <value>[base64 mime encoded serialized .NET Framework object]</value> - </data> - <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> - <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> - <comment>This is a comment</comment> - </data> - - There are any number of "resheader" rows that contain simple - name/value pairs. - - Each data row contains a name, and value. The row also contains a - type or mimetype. Type corresponds to a .NET class that support - text/value conversion through the TypeConverter architecture. - Classes that don't support this are serialized and stored with the - mimetype set. - - The mimetype is used for serialized objects, and tells the - ResXResourceReader how to depersist the object. This is currently not - extensible. For a given mimetype the value must be set accordingly: - - Note - application/x-microsoft.net.object.binary.base64 is the format - that the ResXResourceWriter will generate, however the reader can - read any of the formats listed below. - - mimetype: application/x-microsoft.net.object.binary.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.soap.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Soap.SoapFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.bytearray.base64 - value : The object must be serialized into a byte array - : using a System.ComponentModel.TypeConverter - : and then encoded with base64 encoding. - --> - <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> - <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> - <xsd:element name="root" msdata:IsDataSet="true"> - <xsd:complexType> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="metadata"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - <xsd:attribute name="name" use="required" type="xsd:string" /> - <xsd:attribute name="type" type="xsd:string" /> - <xsd:attribute name="mimetype" type="xsd:string" /> - <xsd:attribute ref="xml:space" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="assembly"> - <xsd:complexType> - <xsd:attribute name="alias" type="xsd:string" /> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="data"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> - <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> - <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> - <xsd:attribute ref="xml:space" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="resheader"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - </xsd:element> - </xsd:choice> - </xsd:complexType> - </xsd:element> - </xsd:schema> - <resheader name="resmimetype"> - <value>text/microsoft-resx</value> - </resheader> - <resheader name="version"> - <value>2.0</value> - </resheader> - <resheader name="reader"> - <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <resheader name="writer"> - <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> -</root> \ No newline at end of file
--- a/Implab.Diagnostics.Interactive/TraceViewItem.cs Thu Apr 17 08:49:24 2014 +0400 +++ b/Implab.Diagnostics.Interactive/TraceViewItem.cs Thu Apr 17 18:49:36 2014 +0400 @@ -5,10 +5,21 @@ using System.Threading.Tasks; namespace Implab.Diagnostics.Interactive { - public struct TraceViewItem { - public string message; - public int timestamp; - public int indent; - public int thread; + public class TraceViewItem { + string m_formattedValue; + + public string Message { get; set; } + public int Timestamp { get; set; } + public int Indent { get; set; } + public int Thread { get; set; } + + public string FormattedMessage { + get { + if (m_formattedValue == null) { + m_formattedValue = Message.Replace("\r",String.Empty).Replace("\n", " | "); + } + return m_formattedValue; + } + } } }
--- a/Implab/Diagnostics/TextFileListener.cs Thu Apr 17 08:49:24 2014 +0400 +++ b/Implab/Diagnostics/TextFileListener.cs Thu Apr 17 18:49:36 2014 +0400 @@ -23,6 +23,7 @@ lock (m_textWriter) { if (!IsDisposed) { + // тут гарантировано еще не освобожден m_textWriter m_textWriter.WriteLine(msg.ToString()); m_textWriter.Flush(); } @@ -33,6 +34,7 @@ protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { + // IsDisposed = true lock (m_textWriter) { Safe.Dispose(m_textWriter); }
--- a/Implab/Diagnostics/TextListenerBase.cs Thu Apr 17 08:49:24 2014 +0400 +++ b/Implab/Diagnostics/TextListenerBase.cs Thu Apr 17 18:49:36 2014 +0400 @@ -89,6 +89,15 @@ } } + /// <summary> + /// Вызывается для записи текста сообщения, в журнал. + /// </summary> + /// <remarks> + /// Данный метод может вызваться из разных потоков одновременно. Возможна ситуация, когда + /// данный метод вызывается уже после освобождения ообъекта методом <see cref="Dispose()"/>. + /// </remarks> + /// <param name="context">Контекст трассировки.</param> + /// <param name="text">Текст сообщения.</param> protected abstract void WriteEntry(TraceContext context, EventText text); public EventText Format(TraceContext context, object data) { @@ -110,10 +119,10 @@ } protected override void Dispose(bool disposing) { + base.Dispose(disposing); if (disposing) { UnsubscribeAll(); } - base.Dispose(disposing); } } }