c# – WCF服务应用程序 – 使用C对象调用导致Visual Basic 6.0 DLL文件挂起

c# – WCF服务应用程序 – 使用C对象调用导致Visual Basic 6.0 DLL文件挂起,第1张

概述我们目前正在将系统移动到使用 WCF,并遇到了一个我们无法弄清楚的问题.安装程序是一个C#DLL文件,包装C和Visual Basic 6.0 DLL文件. C#DLL文件具有这两者的包装器,并实例化这两个对象.初始化C对象(从文件中获取数据),然后将其传递给Visual Basic 6.0对象,该对象使用C对象中的数据运行报表.这一切都发生在WCF服务应用程序中,并且大多数情况下都很好用,但是当 我们目前正在将系统移动到使用 WCF,并遇到了一个我们无法弄清楚的问题.安装程序是一个C#DLL文件,包装C和Visual Basic 6.0 DLL文件. C#DLL文件具有这两者的包装器,并实例化这两个对象.初始化C对象(从文件中获取数据),然后将其传递给Visual Basic 6.0对象,该对象使用C对象中的数据运行报表.这一切都发生在WCF服务应用程序中,并且大多数情况下都很好用,但是当Visual Basic 6.0代码调用C对象中的方法时,整个事情就会挂起.

我只使用一个调用相同C#DLL文件(在WCF之外)的简单应用程序进行测试,并且它可以完美地工作.所以,WCF和那个C DLL文件正在发生一些事情,但我们无法弄清楚是什么.我已经将Visual Basic 6.0 DLL文件更改为使用Run Unattended和Store in Memory(以便能够使用它),但这似乎并不重要.

有没有人有这方面的经验,或者有任何想法为什么会挂?我的想法是WCF服务以某种方式锁定DLL文件,这就是为什么当Visual Basic 6.0 DLL文件使用它时,它无法访问它,导致它死锁.

C包装

public interface ISummaryWrapper    {        voID LoadInfo(Application info);        SummaryApp GetSummary();    }    public class SummaryWrapper : ISummaryWrapper    {        private SummaryApp _summary;        public SummaryWrapper()        {            _summary = new SummaryApp();        }        public SummaryWrapper(Application info)        {            _summary = new SummaryApp();            LoadInfo(info);        }        public voID LoadInfo(Application info)        {            _summary.Initialize(info);        }        public SummaryApp GetSummary()        {            return _summary;        }    }

info对象包含有关Summary对象需要生成的内容的信息.它仅用于Initialize方法.

Visual Basic 6.0对象通过接口加载:

public voID LoadPageObject(Application info){    _pageInfo = new Pageinformation();    _pageInfo.oInfo = info;    _pageInfo.oSummary = _summary;}

所以现在Visual Basic 6.0对象Pageinformation有了摘要对象.

接下来,我们调用该方法来生成报告:

_pageInfo.buildreport();

这在Visual Basic 6.0 DLL文件中,并且在代码尝试使用摘要对象时,它会挂起

// Omitted actual params for brevity,though all the params existdouble value = oSummary.GetData(string parm1,string parm2)

如果我在C#中使用同一个调用,它会将数据拉回来.

double value = _summary.GetData(string parm1,string parm2);

同样,当我在WCF之外使用这个包装器时,它会很好地完成代码.只有当它在WCF中运行时它才会挂起.

这似乎是在MTA中运行的问题,我不确定在IIS上运行的WCF服务应用程序是否可以设置为在STA中运行.这可能吗?

解决了:
我在Stack Overflow问题中找到了答案:

How to make a WCF service STA (single-threaded)

这引出了我的文章XXX.

基本上,我必须创建一个设置为STA的线程,并在其中运行API(我的C#DLL文件).由于我使用TaskFactory运行所有这些(所以我可以取消调用,并运行多个请求),这有点棘手.现在,我仍然可以在MTA中同时运行多个报告,但每个报告都在STA中运行.此外,我也不会失去WCF的取消功能.

这是代码(我还有一些清理工作):

public class Builder{    public string OperationID { get; set; }    public IServiceCallback CallBack { get; set; }    public Dictionary<string,CancellationTokenSource> Queue { get; set; }    public voID buildreport()    {        OperationContext context = OperationContext.Current;        Thread thread = new Thread(            new ThreadStart(                delegate                    {                        using (OperationContextScope scope = new OperationContextScope(context))                        {                            try                            {                                CancellationToken token = Queue[OperationID].Token;                                CallBack.SendStatus(OperationID,Status.Processing);                                IAPI API = new API(token);                                API.MessagingEvents += MessageEvent;                                // Build Report                                CallBack.SendStatus(OperationID,Status.BuildingReport);                                if (!API.buildreport())                                    return;                                CallBack.SendStatus(OperationID,Status.Completed);                            }                            catch (OperationCanceledException oc)                            {                                // Sending this on the method that receives the cancel request,no need to send again                            }                            catch (Exception ex)                            {                                // May not be able to use callback if it's a Timeout Exception,log error first                                // Todo: Log Error                                CallBack.SendMessage(OperationID,MessageType.Error,ex.Message);                                CallBack.SendStatus(OperationID,Status.Error);                            }                            finally                            {                                Queue.Remove(OperationID);                            }                        }                    }));        thread.SetApartmentState(ApartmentState.STA);        thread.Start();        thread.Join();    }}

我的服务通过以下方式调用:

// I initialize taskfactory when the service is created,omitting other code for brevitypublic voID buildreport(ReportRequest request){    CallBack.SendReportStatus(request.OperationID,Status.Received);    CancellationTokenSource cancelSource = new CancellationTokenSource();    Queue.Add(request.OperationID,cancelSource);    Builder builder = new Builder    {        OperationID = request.OperationID,CallBack = CallBack,Queue = _queue    };    _taskFactory.StartNew(builder.buildreport,cancelSource.Token);}

我希望这可以帮助遇到这个问题的任何人!

解决方法 需要从STA线程运行VB6(COM).您的WCF代码可能正在调用一个或多个MTA线程上的VB6组件.我打赌你的测试(非WCF)应用程序,一个有效的,是一个桌面应用程序.您需要确保不从任意.NET线程调用VB6组件. 总结

以上是内存溢出为你收集整理的c# – WCF服务应用程序 – 使用C对象调用导致Visual Basic 6.0 DLL文件挂起全部内容,希望文章能够帮你解决c# – WCF服务应用程序 – 使用C对象调用导致Visual Basic 6.0 DLL文件挂起所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1228480.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存