【问题标题】:Xamarin Forms unhandledexception loggingXamarin Forms 未处理异常日志记录
【发布时间】:2016-04-28 11:31:38
【问题描述】:

我想在我的 Xamarin PCL(便携式类库)中捕获所有未处理的异常,但不知道如何连接 UnhandledException 方法?

我可以看到我可以在 windows(device) 特定项目中做到这一点;但不在 PCL 中?

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

更新

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

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

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

有没有办法以非异步方式写入文件,因为异步似乎无处不在;让这变得相当困难。

【问题讨论】:

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


    【解决方案1】:

    试试这个:

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

    【讨论】:

    • 嗨 Softlion,我已经尝试了第一段代码,但该事件没有受到影响!我无法弄清楚将 AppDomain.CurrentDomain 代码放在哪里,因为我的 Windows 8.1 应用程序似乎没有 AppDomain(找不到它)
    • 不要把它放到你的 PCL 中,只放到最终的应用项目中
    • @Softlion 能否请您澄清一下,哪些代码可以在 PCL 中,哪些必须在平台项目中,好吗?以后请避免说“这个”。
    • @Edgaras pcl 不存在了。
    【解决方案2】:

    我通过阻止主线程存在直到日志被写入来让它工作。这是从 Windows 项目中针对 App.xaml.cs 主文件完成的。

    需要注意的主要部分是 ManualResetEvent 对象以及 WaitOneSet 方法的调用,它们将阻止和恢复主线程。

    我也必须将异常存储在一个变量中,因为如果我直接在匿名异步方法中使用 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);
    }
    

    【讨论】:

    • 这仅适用于 windows 项目而不是 xamarin 表单
    猜你喜欢
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 2014-10-28
    • 2011-10-20
    相关资源
    最近更新 更多