【发布时间】:2017-10-19 09:14:44
【问题描述】:
PDFTron 似乎无法处理多个 AppDomain。从单独的 AppDomain 运行 PDFTron 时,应用程序崩溃并出现未处理的异常(“无法跨 AppDomain 传递 GCHandle”)。
bei System.Runtime.InteropServices.GCHandle.InternalCheckDomain(IntPtr handle)
bei System.Runtime.InteropServices.GCHandle.FromIntPtr(IntPtr value)
bei gcroot<pdftron::PDF::PDFViewWPF ^>.->(gcroot<pdftron::PDF::PDFViewWPF ^>* )
bei pdftron.PDF.detail.DeluxeCreateTile(Void* data, SByte* buffer, UInt32 width, UInt32 height, UInt32 stride, UInt32 page_num, UInt64 x_page_loc, UInt64 y_page_loc, UInt32 zoomed_page_width, UInt32 zoomed_page_height, UInt32 tile_id, UInt32 x_in_page, UInt32 y_in_page, Int32 canvas_id, Int32 remaining_tiles, Int32 tile_type, Int32 sequenceNum)
在搜索解决方案时,我在 2011 年创建的 Google Groups 论坛中找到了一个主题。用户在他正在开发的 Outlook 插件中遇到了同样的异常。根据主题,PDFTron 支持已经知道该问题,并且在基于 WinForms 的控件之一中也已修复。你可以在这里找到讨论:https://groups.google.com/forum/#!topic/pdfnet-sdk/DGki3Fj2_FU
我是否必须考虑某些事情,或者 PDFTron 根本无法在这种环境中运行?
这是我用来重现问题的示例中的代码:
MainWindow.xaml
<Window x:Class="RunningPdfTronUsingMultipleAppDomains.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RunningPdfTronUsingMultipleAppDomains"
xmlns:pdf="clr-namespace:pdftron.PDF;assembly=PDFNet"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="LayoutRoot">
<pdf:PDFViewWPF x:Name="PDFView"/>
<Button Panel.ZIndex="100" Height="20" Width="110" Content="Create AppDomain" PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown"/>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
PDFDoc document = new PDFDoc("SampleDocument.pdf");
PDFView.SetDoc(document);
}
private void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
AppDomain appDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
var assembly = System.Reflection.Assembly.GetAssembly(typeof(MainWindow));
appDomain.Load(assembly.GetName());
Proxy proxy = (Proxy)appDomain.CreateInstanceAndUnwrap(System.Reflection.Assembly.GetExecutingAssembly().GetName().FullName, typeof(Proxy).FullName);
Thread thread = new Thread(new ParameterizedThreadStart((o) => proxy.Invoke())) { ApartmentState = ApartmentState.STA };
thread.Start();
}
}
Proxy.cs
public class Proxy : MarshalByRefObject
{
public void Invoke()
{
try
{
App app = new App();
app.Run(new MainWindow());
}
catch (Exception)
{
throw;
}
}
}
【问题讨论】:
-
我不知道 pdftron 的具体情况,但根据错误消息,您只需要确保您不会通过 appdomain 边界传递 GCHandle。您需要这样做吗?
-
我假设 PDFTron 正在这样做。该异常源自 PDFNet SDK 中的“DeluxeCreateTile”方法。
-
我假设您创建了单独的 AppDomain。那么你的工作应该是不要跨域移动 pdftron 相关对象。你能提供一个重现问题的stackoverflow.com/help/mcve吗?
-
我刚刚提供了重现此问题所需的代码。我不知道,是我的代码在域中移动 pdftron 相关对象。那应该是什么对象?
-
我目前无法运行代码,也许其他人可以。在最简约的场景(没有 ui,没有线程)中也会发生同样的情况吗?