我们目前正在移动系统以使用 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 文件更改为使用无人值守运行 和存储在内存中(以便能够以线程方式使用它),但这似乎无关紧要.
有没有人有过这方面的经验,或者对为什么它会被挂起有任何想法?我的想法是 WCF 服务以某种方式锁定了 DLL 文件,这就是为什么当 Visual Basic 6.0 DLL 文件使用它时,它无法访问它,从而导致它死锁。
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;
}
}
信息对象包含有关摘要对象需要生成的内容的信息。它仅在 Initialize 方法中使用。
Visual Basic 6.0 对象通过接口(interface)加载:
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 问题中找到了答案:
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 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);
}
我希望这对遇到此问题的其他人有所帮助!
最佳答案
VB6 (COM) 需要从 STA 线程运行。您的 WCF 代码可能在一个或多个 MTA 线程上调用 VB6 组件。我敢打赌,您的测试(非 WCF)应用程序是一个桌面应用程序,该应用程序可以正常工作。您将需要确保不会从任意 .NET 线程调用 VB6 组件。
关于c# - WCF 服务应用程序 - 使用 C++ 对象调用导致 Visual Basic 6.0 DLL 文件挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8125675/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file