66using System . Threading ;
77using System . Threading . Tasks ;
88using System . Windows . Forms ;
9+ using System . Collections . Concurrent ;
910using log4net . Appender ;
1011using log4net . Config ;
1112using log4net . Core ;
@@ -16,6 +17,13 @@ namespace NMaier.SimpleDlna.GUI
1617{
1718 public partial class FormMain : Form , IAppender , IDisposable
1819 {
20+ private struct LogEntry
21+ {
22+ public string Level ;
23+ public string Message ;
24+ public string Class ;
25+ public string Exception ;
26+ }
1927 private bool logging = false ;
2028 private static readonly Properties . Settings Config = Properties . Settings . Default ;
2129 private HttpServer httpServer ;
@@ -26,6 +34,8 @@ public partial class FormMain : Form, IAppender, IDisposable
2634 private readonly FileInfo logFile = new FileInfo ( Path . Combine ( cacheDir , "sdlna.log" ) ) ;
2735#endif
2836 private bool canClose = false ;
37+ private readonly System . Timers . Timer logAppendTimer = new System . Timers . Timer ( 500 ) ;
38+ private readonly ConcurrentQueue < LogEntry > pendingLogEntries = new ConcurrentQueue < LogEntry > ( ) ;
2939
3040 private static string cacheDir
3141 {
@@ -95,6 +105,8 @@ private void SetupLogging()
95105 RollingStyle = RollingFileAppender . RollingMode . Size
96106 } ;
97107 fileAppender . ActivateOptions ( ) ;
108+
109+ logAppendTimer . Elapsed += DoAppendInternal ;
98110 BasicConfigurator . Configure ( this , fileAppender ) ;
99111 }
100112
@@ -228,21 +240,48 @@ public void DoAppend(LoggingEvent loggingEvent)
228240 }
229241 var cls = loggingEvent . LoggerName ;
230242 cls = cls . Substring ( cls . LastIndexOf ( '.' ) + 1 ) ;
231- BeginInvoke ( new logDelegate ( ( lvl , lg , msg , ex ) =>
243+ pendingLogEntries . Enqueue ( new LogEntry ( )
232244 {
233- if ( ! logging ) {
234- return ;
235- }
236- if ( logger . Items . Count >= 300 ) {
237- logger . Items . RemoveAt ( 0 ) ;
238- }
239- logger . EnsureVisible ( logger . Items . Add ( new ListViewItem ( new string [ ] { lvl , lg , msg } ) ) . Index ) ;
240- if ( ! string . IsNullOrWhiteSpace ( ex ) ) {
241- logger . EnsureVisible ( logger . Items . Add ( new ListViewItem ( new string [ ] { lvl , lg , ex } ) ) . Index ) ;
245+ Class = cls ,
246+ Exception = loggingEvent . GetExceptionString ( ) ,
247+ Level = loggingEvent . Level . DisplayName ,
248+ Message = loggingEvent . RenderedMessage
249+ } ) ;
250+ lock ( logAppendTimer ) {
251+ logAppendTimer . Enabled = true ;
252+ }
253+ }
254+
255+ public void DoAppendInternal ( object sender , System . Timers . ElapsedEventArgs e )
256+ {
257+ lock ( logAppendTimer ) {
258+ logAppendTimer . Enabled = false ;
259+ }
260+ if ( ! logging ) {
261+ return ;
262+ }
263+ LogEntry entry ;
264+ int last = - 1 ;
265+ logger . BeginUpdate ( ) ;
266+ try {
267+ while ( pendingLogEntries . TryDequeue ( out entry ) ) {
268+ if ( logger . Items . Count >= 300 ) {
269+ logger . Items . RemoveAt ( 0 ) ;
270+ }
271+ last = logger . Items . Add ( new ListViewItem ( new string [ ] { entry . Level , entry . Class , entry . Message } ) ) . Index ;
272+ if ( ! string . IsNullOrWhiteSpace ( entry . Exception ) ) {
273+ last = logger . Items . Add ( new ListViewItem ( new string [ ] { entry . Level , entry . Class , entry . Exception } ) ) . Index ;
274+ }
242275 }
276+ }
277+ finally {
278+ logger . EndUpdate ( ) ;
279+ }
280+ if ( last != - 1 ) {
281+ logger . EnsureVisible ( last ) ;
243282 colLogLogger . AutoResize ( ColumnHeaderAutoResizeStyle . ColumnContent ) ;
244283 colLogMessage . AutoResize ( ColumnHeaderAutoResizeStyle . ColumnContent ) ;
245- } ) , loggingEvent . Level . DisplayName , cls , loggingEvent . RenderedMessage , loggingEvent . GetExceptionString ( ) ) ;
284+ }
246285 }
247286
248287 private void notifyIcon_DoubleClick ( object sender , EventArgs e )
0 commit comments