【发布时间】:2018-05-14 03:36:00
【问题描述】:
我有一个 WPF-MVVM 应用程序。我想在加载和处理文件时使用async 和await 使我的UI 响应。当 awaited 的方法使用 log4net 进行日志记录时,我收到异常“调用线程无法访问此对象,因为不同的线程拥有它”。
// The method returns 'void' because it is used by a DelegateCommand!
private async void LoadAndProcessFileAsync()
{
this.MyBindingList.Clear(); // Works fine
var importer = await Task.Run(() => new Importer());
this.MyBindingList.Clear(); // Exception
}
进口商所做的只是:
public class Importer
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public Importer()
{
log.Info("Test");
}
}
如果我注释掉log.Info... 和静态ILog-变量,一切正常。如果我执行以下操作也会出现问题:
private async void LoadAndProcessFileAsync()
{
this.MyBindingList.Clear(); // Works fine
var test = await Task.Run(() => Math.Sqrt(9));
var importer = new Importer();
this.MyBindingList.Clear(); // Exception
}
如果我在 async 方法中根本不使用 await,它就会消失。
为什么会这样?如何同时使用await 和登录? (我正在使用使用 log4net 的第三方库,所以我无法更改该代码...)。
【问题讨论】:
-
如果您将日志设为非静态,则可以肯定不会出现问题。静态日志意味着您在多个线程中使用相同的对象;因此,为什么除了主线程(在初始化期间创建所有静态对象的线程)之外的线程在访问它时存在问题。
-
如果
Importer是您不拥有的第三方库,您怎么知道它会做什么? -
@Evk:我写了
Importer来重现错误。第三方库是 xBim(开源),我必须检查他们如何准确地处理他们的日志记录。 -
所以澄清一下,这是重现问题的确切代码,而不是一些伪代码?
-
那么值得发布可以重现此行为的确切代码,而无需剥离任何内容(嗯,与重现相关的任何内容),因为使用当前代码它是不可重现的。
标签: c# wpf async-await log4net ui-thread