Xamarin表示unhandledexception记录

时间:2016-04-28 11:31:39

标签: c# logging xamarin error-handling xamarin.forms

我想在我的Xamarin PCL(可移植类库)中捕获所有未处理的异常,但是无法弄清楚如何连接 UnhandledException 方法?

我可以看到我可以在windows(设备)特定项目中完成它;但不是在PCL中?

我基本上是尝试使用PCLStorage来记录错误,但这阻止了我。

更新

我还尝试使用依赖服务通过非PCL方法进行写入。 当抛出错误时,它会被自动生成的 App.gi.cs 文件捕获。然后它传播到UnhandledException方法,我已经连接了窗口8.1项目。

我曾尝试使用依赖服务写入文件,但由于代码是异步的,因此认为它在写入日志之前就已退出,因为它是一个未处理的异常。

await DependencyService.Get<IFileWriter>().ErrorAsync(e.Exception);

有没有办法以非异步方式写入文件,因为async似乎到处都是;使这很困难。

2 个答案:

答案 0 :(得分:2)

试试这个:

        TaskScheduler.UnobservedTaskException += (s, e) =>
        {
            Mvx.Error("Task exception from {0}: {1}", s.GetType(), e.Exception.ToString());
            if (!e.Observed)
                e.SetObserved();
        };

这仅适用于最终的应用程序项目,但也会捕获由PCL库触发的所有异常。

        AppDomain.CurrentDomain.UnhandledException += (s, e) =>
        {
            var ex = e.ExceptionObject as Exception;
            Mvx.Error("Domain Exception from  {0}: {1}", s.GetType(), ex != null ? ex.ToString() : e.ToString());
        };

答案 1 :(得分:-1)

我通过阻止主线程从现有开始直到写入日志为止。这是通过Windows Project为主 App.xaml.cs 文件完成的。

需要注意的主要内容是 ManualResetEvent 对象以及调用 WaitOne 设置方法,这些方法将阻止并恢复主线。

我不得不将异常存储在变量中,因为如果我在匿名异步方法中直接使用 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 Window项目代码方法。

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);
}