WCF服务应用程序 – 使用C ++对象调用导致Visual Basic 6.0 DLL文件挂起
我们目前正在移动系统以使用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 ++ Wrapper
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 exist double value = oSummary.GetData(string parm1, string parm2)
如果我在C#中使用相同的调用,它会将数据拉回来。
double value = _summary.GetData(string parm1, string parm2);
再次,当我在WCF之外使用这个包装器时,它会很好地完成代码。 只有当它在WCF中运行时它才会挂起。
这似乎是在MTA中运行的问题,我不确定在IIS上运行的WCF服务应用程序是否可以设置为在STA中运行。 这可能吗?
已解决:我在Stack Overflow问题中找到了答案:
如何制作WCF服务STA(单线程)
这引出了我的文章XXX 。
基本上,我必须创建一个设置为STA的线程,并在其中运行API(我的C#DLL文件)。 由于我使用TaskFactory运行所有这些(所以我可以取消调用,并运行多个请求),这有点棘手。 现在,我仍然可以在MTA中同时运行多个报告,但每个报告都在STA中运行。 此外,我也不会失去WCF的取消function。
这是代码(我还有一些清理工作):
public class Builder { public string OperationId { get; set; } public IServiceCallback CallBack { get; set; } public Dictionary 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 brevity public 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#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/949836.html