2012-05-08 24 views
11

Tôi muốn tắt ứng dụng của mình và viết bất kỳ thông điệp tường trình đang chờ xử lý nào. Vì vậy, tôi gọi LogManager.Flush() trong quá trình tắt máy của tôi. Tuy nhiên, tôi không thấy tất cả các tin nhắn được viết ra. Thay vào đó, nếu tôi đợi một vài giây (sử dụng Thread.Sleep()), tôi sẽ thấy các tin nhắn.NLog có nên xóa tất cả các thư được xếp hàng đợi trong AsyncTargetWrapper khi Flush() được gọi không?

Sau khi kiểm tra NLog's code on GitHUB, tôi tìm thấy phương pháp AsyncTargetWrapper.FlushAsync() chỉ lập lịch trình chuỗi ghi chú lười để viết tất cả thư đang chờ xử lý vào đợt tiếp theo. Nó không phải là viết tin nhắn đăng nhập đồng bộ.

Đây có phải là hành vi mong đợi không? Tôi mong đợi LogManager.Flush() sẽ được đồng bộ, tức là: chặn cho đến khi tất cả các thư đang chờ xử lý được ghi (hoặc quá thời gian chờ bị vượt quá).


Mã tôi sử dụng trên shutdown:

LogManager.Flush(ex => { }, TimeSpan.FromSeconds(15)); 

Và sau đó mã để khởi nLog (đây là một ứng dụng Silverlight, vì vậy tôi không sử dụng bất kỳ tập tin config).

public static void InitialiseNLog(LogLevel forLevel) 
    { 
     var config = new LoggingConfiguration(); 

     // Add targets. 
     // We need an async target wrapping a custom web service call back to the server. 
     var serverTarget = new RemoteServiceTarget(); 
     var asyncWrapper = new AsyncTargetWrapper(serverTarget, 10000, AsyncTargetWrapperOverflowAction.Discard); 
     asyncWrapper.TimeToSleepBetweenBatches = (int)TimeSpan.FromSeconds(2).TotalMilliseconds; 
     asyncWrapper.BatchSize = 200; 

     // Add rules. 
     var rule = new LoggingRule("Company.Application.SilverlightApp.*", forLevel, asyncWrapper); 
     config.LoggingRules.Add(rule); 

     // Activate the configuration. 
     LogManager.Configuration = config; 
     LogManager.GlobalThreshold = forLevel; 
    } 

Trả lời

-1

Tôi đã khắc phục bằng cách chỉnh sửa mã nguồn NLog hiện tại.

Trong AsyncTargetWrapper.cs, thay đổi phương pháp FlushAsync() từ:

protected override void FlushAsync(AsyncContinuation asyncContinuation) 
{ 
    this.flushAllContinuation = asyncContinuation; 
} 

Để:

protected override void FlushAsync(AsyncContinuation asyncContinuation) 
{ 
    this.flushAllContinuation = asyncContinuation; 
    this.ProcessPendingEvents(null);  // Added to make this flush synchronous. 
} 
+1

Kết quả FlushAsync chức năng trở thành đồng bộ ;-) Đây không phải là một sửa chữa. –

+0

Đây là một chút cũ, vì vậy tôi không thể nhớ toàn bộ ngữ cảnh. Nhưng việc gọi 'Thread.Sleep()' khi tắt máy hầu như không phải là một lựa chọn tốt hơn. Có một phương thức 'LogManager.Shutdown()' trong NLog hiện tại, có thể là một lựa chọn tốt hơn (mặc dù tôi chưa thử nghiệm nó). – ligos

0

Vẫn không hoàn hảo, nhưng làm thế nào về điều này:

var reset = new ManualResetEventSlim(false); 
LogManager.Flush(ex => reset.Set(), TimeSpan.FromSeconds(15)); 
reset.Wait(TimeSpan.FromSeconds(15)); 
3

Các bình luận bởi ligos đang đi đúng hướng. Phương pháp AsyncTargetWrapper.CloseTarget() đã được sửa đổi là kết quả của NLog issue 134, trong đó lồng nhau BufferingTargetWrapper không bị xóa khi tải miền.

LogManager.Shutdown() không thực sự buộc các AsyncTargetWrapper hiệu quả tuôn ra đồng bộ nhưng nó sẽ phải được sử dụng sau khi LogManager.Flush() vì mục tiêu như BufferingTargetWrapper không thực sự tuôn ra trên gần. Nó có thể tốt hơn để đặt LogManager.Configuration = null vì điều này thực hiện một tuôn ra và sau đó đóng các mục tiêu trong một lần truy cập và cấu hình sẽ được tải lại (nếu sử dụng tệp cấu hình) vào lần tiếp theo nó cần được sử dụng.

Tôi đã thử nghiệm cả hai và tôi đã đi với sau này như tôi muốn đăng nhập của tôi sao lưu và chạy sau khi tôi đã đặt mọi thứ đúng, nhưng với câu hỏi là trong Silverlight Tôi muốn giới thiệu:

LogManager.Flush(); 
LogManager.Shutdown(); 

Sửa

LogManager đặt cấu hình để null trên dỡ bỏ miền hoặc quá trình thoát vì vậy chúng tôi không nên nhìn thấy vấn đề này trừ khi chạy một phiên bản NLog cũ. Vấn đề NLog đã được sửa vào tháng 10 năm 2012. Đã thử nghiệm mà không tắt hoặc tắt cấu hình thiết lập thành null và có thể xác nhận rằng việc gọi LogManager.Flush() là đủ.

Các vấn đề liên quan