在我的应用程序(.NET 4.0)中,我使用smartassembly进行自定义模板的错误报告。它安装了两个处理程序:
在一台客户的计算机(Windows XP,.NET 4.0)上,他在应用程序启动后收到来自#2的错误消息。然后申请被终止:
System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.
at System.Windows.Threading.Dispatcher.VerifyAccess()
at Exapt.ErrorReporting.ErrorReportView..ctor()
at Exapt.ErrorReporting.ExaptUnhandledExceptionHandler.OnReportException(ReportExceptionEventArgs e)
at SmartAssembly.SmartExceptionsCore.UnhandledExceptionHandler.ReportException(Exception exception, Boolean canContinue, Boolean manuallyReported)
相关代码:
public ExaptUnhandledExceptionHandler : UnhandledExceptionHandler
{
protected override void OnReportException(ReportExceptionEventArgs e)
{
var view = new ErrorReportView();
view.DataContext = new ErrorReportViewModel(this, e, view);
view.ShowDialog();
}
}
public ErrorReportView : Window
{
public ErrorReportView()
{
this.InitializeComponent();
// EDIT
if (Application.Current != null)
this.Owner = Application.Current.MainWindow;
// END EDIT
}
}
所以发生以下情况:
InitializeComponent()
之前)! 一个简单的新Window()如何可能导致自身的跨线程异常?
答案 0 :(得分:2)
尝试使用WPF ErrorReportView
创建Dispatcher
:
public ExaptUnhandledExceptionHandler : UnhandledExceptionHandler
{
protected override void OnReportException(ReportExceptionEventArgs e)
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
var view = new ErrorReportView();
view.DataContext = new ErrorReportViewModel(this, e, view);
view.ShowDialog();
}));
}
}
由于我无法测试或重现您的问题,我不确定它是否有效,但值得一试。
答案 1 :(得分:1)
选项是触发专用线程来处理此报告。它会是这样的:
[TestMethod]
public void TestMethod1()
{
MainWindow window = null;
// The dispatcher thread
var t = new Thread(() =>
{
window = new MainWindow();
// Initiates the dispatcher thread shutdown when the window closes
window.Closed += (s, e) => window.Dispatcher.InvokeShutdown();
window.Show();
// Makes the thread support message pumping
System.Windows.Threading.Dispatcher.Run();
});
// Configure the thread
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
请注意:
您可以在this link。
中找到更多信息答案 2 :(得分:0)
通过Arthur Nunes的回答和Sisyphe的回答,我现在处理所有可能性。显然是在STA线程上抛出异常,但该线程不是主(UI)线程。可能由于JIT优化,我得到的堆栈跟踪有点不完整,并显示异常发生在错误的位置。
固定代码:
public ExaptUnhandledExceptionHandler : UnhandledExceptionHandler
{
protected override void OnReportException(ReportExceptionEventArgs e)
{
// Create a new STA thread if the current thread is not STA.
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
{
this.ShowErrorReportView(e);
}
else
{
// Since I use ShowDialog() below, there is no need for Dispatcher.Run()
// or Dispatcher.InvokeShutdown()
var thread = new Thread(() => this.ShowErrorReportView(e));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
}
private void ShowErrorReportView(ReportExceptionEventArgs e)
{
var view = new ErrorReportView();
view.DataContext = new ErrorReportViewModel(this, e, view);
view.ShowDialog();
}
}
public ErrorReportView : Window
{
public ErrorReportView()
{
this.InitializeComponent();
// All of these cause accessing the MainWindow property or setting the Owner
// to throw an exception.
if (Application.Current != null
&& Application.Current.Dispatcher.CheckAccess()
&& Application.Current.MainWindow != null
&& Application.Current.MainWindow != this
&& Application.Current.MainWindow.IsLoaded)
{
this.Owner = Application.Current.MainWindow;
}
}
}