草庐IT

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

coder 2024-02-25 原文

我们目前正在移动系统以使用 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 文件使用它时,它无法访问它,从而导致它死锁。

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;
        }
    }

信息对象包含有关摘要对象需要生成的内容的信息。它仅在 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/

有关c# - WCF 服务应用程序 - 使用 C++ 对象调用导致 Visual Basic 6.0 DLL 文件挂起的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用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请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行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

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  7. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的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

  8. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在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

  9. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  10. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到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

随机推荐