我通过阻止主线程存在直到日志被写入来让它工作。这是从 Windows 项目中针对 App.xaml.cs 主文件完成的。
需要注意的主要部分是 ManualResetEvent 对象以及 WaitOne 和 Set 方法的调用,它们将阻止和恢复主线程。
我也必须将异常存储在一个变量中,因为如果我直接在匿名异步方法中使用 e.Exception,它会丢失堆栈跟踪。
private static readonly ManualResetEvent resetEvent = new ManualResetEvent(false);
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.UnhandledException += (sender, e) =>
{
var exception = e.Exception;
Task.Run(async () =>
{
await DependencyService.Get<IFileWriter>().ErrorAsync(exception);
resetEvent.Set();
});
resetEvent.WaitOne();
};
}
为了更加完整,我已经包含了 DependencyService 窗口的项目代码方法,该方法写入本地存储。
private async Task WriteToLogFile(string message, string messageType)
{
var storageFolder = await GetStorageFolder();
var file = await storageFolder.CreateFileAsync(FormatDateForLogName(), CreationCollisionOption.OpenIfExists);
try
{
using (StreamWriter writer = new StreamWriter(await file.OpenStreamForWriteAsync(), Encoding.UTF8))
{
writer.BaseStream.Seek(writer.BaseStream.Length, SeekOrigin.Begin);
writer.Write(string.Format("{0}{1} - {2}: {3}", System.Environment.NewLine, FormatLogPrefix(), messageType, message));
}
}
catch (Exception err)
{
System.Diagnostics.Debug.WriteLine(err.Message);
}
}
private async Task<StorageFolder> GetStorageFolder()
{
StorageFolder local = ApplicationData.Current.LocalFolder;
return await local.CreateFolderAsync(LogFolderName, CreationCollisionOption.OpenIfExists);
}