使我的 COM 程序集调用异步

2024-05-15

我刚刚“赢得”了在当前工作中维护用 C# 编码的遗留库的特权。

这个dll:

  • 公开使用 Uniface 构建的大型遗留系统的方法,除了调用 COM 对象之外别无选择。
  • 充当此遗留系统与另一个系统的 API 之间的链接。
  • 在某些情况下,使用 WinForm 作为其 UI。

更直观地,据我了解这些组件:

*[Big legacy system in Uniface]* ==[COM]==> [C# Library] ==[托管API]==> *[Big EDM Management System]*

问题是:此 C# 库中的方法之一运行时间太长,我"should"使其异步!

我习惯了 C#,但根本不习惯 COM。我已经完成了并发编程,但 COM 似乎增加了很多复杂性,到目前为止我的所有试验都以以下任一方式结束:

  • 完全没有错误消息的崩溃
  • 我的 Dll 仅部分工作(仅显示其 UI 的一部分,然后关闭),并且仍然没有给我任何错误

我没有关于如何处理 COM dll 中的线程的想法和资源,如果有任何提示或帮助,我将不胜感激。

到目前为止,我更改的代码的最大部分是使我的方法异步:

// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
  errMsg = "";
  try {
    Action<string> asyncOp = AsyncComparedSearch;
    asyncOp.BeginInvoke(application, null, null);
  } catch (ex) {
    // ...
  }
  return 0;
}

private int AsyncComparedSearch(string application) {
  // my actual method doing the work, that was the called method before
}

任何提示或有用的资源将不胜感激。 谢谢。

更新1:

遵循下面的答案和线索(特别是关于SynchronizationContext,并在帮助下这个例子 http://blogs.msdn.com/b/mattdotson/archive/2006/02/13/531315.aspx)我能够重构我的代码并使其正常工作,但仅限于从 C# 中的另一个 Window 应用程序调用时,而不是通过 COM。 当我调用该函数时,旧系统遇到一个相当模糊的错误,并且没有提供有关崩溃的任何详细信息。

更新2:

我的试验中的最新更新:当从测试项目进行调用时,我设法使多线程工作,并且not来自统一系统。 经过多次试验,我们倾向于认为我们的遗留系统在当前配置中不能很好地支持多线程。但这不再是问题的重点了:)

以下是似乎有效的代码摘录:

string application;
SynchronizationContext context;

// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
    this.application = application;
    context = WindowsFormsSynchronizationContext.Current;
    Thread t = new Thread(new ThreadStart(AsyncComparedSearchAndShowDocs));
    t.Start();
    errMsg = "";
    return 0;
}

private void AsyncComparedSearch() {
    // ANY WORK THAT AS NOTHING TO DO WITH UI
    context.Send(new SendOrPostCallback(
        delegate(object state)
        {
            // METHODS THAT MANAGE UI SOMEHOW
        }
    ), null);
}

我们现在正在考虑修改此 COM 程序集之外的其他解决方案,例如将此库封装在 Windows 服务中并在系统和服务之间创建接口。应该更可持续..


在不了解更多细节的情况下很难判断,但这里存在一些问题。

您通过以下方式在另一个线程上执行委托BeginInvoke但你不会等待。你的try\catch块不会捕获任何内容,因为它已经通过,而远程调用仍在执行。相反,你应该把try\catch挡在里面AsyncComparedSearch.

因为您不等待远程方法执行结束(EndInvoke或通过回调)我不确定你如何处理 COM 调用的结果。我猜你是从内部更新 GUIAsyncComparedSearch。如果是这样,那么它是错误的,因为它正在另一个线程上运行,并且您不应该从 GUI 线程之外的任何地方更新 GUI - 它很可能会导致崩溃或其他意外行为。因此,您需要将 GUI 更新工作同步到 GUI 线程。在WinForms中你需要使用Control.BeginInvoke http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx(不要将其与 Delegate.BeginInvoke 混淆)或其他方式(例如同步上下文 http://msdn.microsoft.com/en-us/magazine/gg598924.aspx) 将代码同步到 GUI 线程。我使用类似的东西:

private delegate void ExecuteActionHandler(Action action);

public static void ExecuteOnUiThread(this Form form, Action action)
{
  if (form.InvokeRequired) { // we are not on UI thread
    // Invoke or BeginInvoke, depending on what you need
    form.Invoke(new ExecuteActionHandler(ExecuteOnUiThread), action);
  }
  else { // we are on UI thread so just execute the action
    action();
  }
}

然后我从任何线程这样称呼它:

theForm.ExecuteOnUiThread( () => theForm.SomeMethodWhichUpdatesControls() );

此外,阅读这个答案 https://stackoverflow.com/questions/10340871/difference-between-delegate-begininvoke-and-using-threadpool-threads-in-c-sharp一些注意事项。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使我的 COM 程序集调用异步 的相关文章

  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 重载<<的返回值

    include
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new

随机推荐