1

我已经编写了带有接口的 ac# 包装类,以使用 GemBox.Document 进行文档转换。在课堂上,我有以下方法来保存文档:

 public string SourcePath{get;set;} 
 public string DestinationType{get;set;}
 public string DestinationPath{get;set;}
 private static DocumentModel document;

 public void ConvertDocument()
 {
            try
            {
               string filename = Path.GetFileNameWithoutExtension(SourcePath);
               ComponentInfo.SetLicense(GemboxLicence); 
               string savePath = String.Format("{0}\\{1}.{2}", DestinationPath, filename, DestinationType);               
               document = DocumentModel.Load(SourcePath);
               document.Save(savePath);

            }
            catch (Exception e)
            {              
                throw (new Exception("An error occured while saving the document: " + e.Message ));   
            }

 }

当我从另一个 c# 程序调用它时,该类工作正常。

我将类的 dll 注册到 com 并使用 regasm 创建了一个 tlb 文件,如下所示:

regasm MBD.GemBox.Document.dll /tlb

我想通过 com 从 delphi 访问 dll,所以我将 tlb 文件导入 Delphi 2009。然后我创建了一个调用 c# dll 的包装器 delphi 库:

procedure ConvertDocument(sourcePath : string ; destinationType : string ; destinationPath : string);
var
     doc : TDocumentConvertor;
begin
  try
      OleInitialize(nil);
      doc := TDocumentConvertor.Create(nil);
      doc.Connect;
      doc.SourcePath := sourcePath ;
      doc.DestinationType := destinationType;
      doc.DestinationPath := destinationPath;
      doc.ConvertDocument;
      doc.Disconnect;
      doc.Free;
      CoUninitialize;
  except
    on E:Exception do
    begin
      Writeln(E.Classname, ': ', E.Message);
    end;
  end;
end;

但是,我得到

“在 GemBox.Document.dll 中发生了 'System.StackOverflowException' 类型的未处理异常”

当我尝试通过delphi调用该方法时。有谁知道为什么会这样?

4

1 回答 1

1

我通过将 Gembox 文档转换部分移动到 c# 代码中的单独线程解决了这个问题:

  string filename = Path.GetFileNameWithoutExtension(SourcePath);
               ComponentInfo.SetLicense(GemboxLicence); 
               string savePath = String.Format("{0}\\{1}.{2}", DestinationPath, filename, DestinationType);               
               document = DocumentModel.Load(SourcePath);
               document.Save(savePath);

解决方案,我创建了一个单独的类,它产生一个单独的线程来处理文档转换:

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Threading;
using GemBox.Document;
using System.Runtime.InteropServices;

namespace  GB.Document
{
    public class GbWorkItem
    {
        public string Source;
        public string Destination;
    }

    internal class GbThreadData
    {
        public bool Running;
        public Queue WorkQueue = Queue.Synchronized(new Queue());
    }

    public class GemBox : IDisposable
    {
        private static GbThreadData _data = new GbThreadData();
        private bool _disposed = false;

        public GemBox()
        {
            Thread thread = new Thread(ThreadExec);
            thread.Start(_data);
        }

        internal static void ThreadExec(object o)
        {
            _data = o as GbThreadData;
            _data.Running = true;

            while (_data.Running)
            {
                if (_data.WorkQueue.Count == 0) Thread.Sleep(250);
                else
                {
                    lock (_data.WorkQueue.SyncRoot)
                    {
                        try
                        {
                            GbWorkItem work = _data.WorkQueue.Dequeue() as GbWorkItem;
                            DocumentModel document = DocumentModel.Load(work.Source);
                            document.Save(work.Destination);
                        }
                        catch (InvalidOperationException) { }
                    }
                }
            }
        }

        public void QueueDocument(GbWorkItem item)
        {
            lock (_data)
            {
                _data.WorkQueue.Enqueue(item);
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;

            if (disposing)
            {
                _data.Running = false;
            }
            _disposed = true;
        }
    }
}

然后我对初始类进行以下更改:

 public string SourcePath{get;set;} 
         public string DestinationType{get;set;}
         public string DestinationPath{get;set;}
         private static DocumentModel document;
         private GemBox _gemBox;

         public DocumentConvertor()
         {       
         Initialise();
         }

         public void ConvertDocument()
         {
                    try
                    {
                       // string filename = Path.GetFileNameWithoutExtension(SourcePath);
                       //ComponentInfo.SetLicense(GemboxLicence); 
                       string savePath = String.Format("{0}\\{1}.{2}", DestinationPath, filename, DestinationType);               
                       // document = DocumentModel.Load(SourcePath);
                       // document.Save(savePath);
                      _gemBox.QueueDocument(new GbWorkItem { Source = SourcePath, Destination = savePath });                  

                    }
                    catch (Exception e)
                    {              
                        throw (new Exception("An error occured while saving the document: " + e.Message ));   
                    }
                    finally
                    {
                      Destroy();
                    }

         }

         private void Initialise()
          {         
             _gemBox = new GemBox();
          }

         private void Destroy()
          {    
             _gemBox.Dispose();
          }

Delphi 代码保持不变。

于 2016-02-09T13:17:59.247 回答