让我的COM组件调用异步 [英] Make my COM assembly call asynchronous

查看:347
本文介绍了让我的COM组件调用异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚赚的特权,以维护传统图书馆在我目前的工作在C#编码

I've just "earned" the privilege to maintain a legacy library coded in C# at my current work.

这DLL:


  • 自曝与UNIFACE做了一个很大的遗留系统,有没有选择,只能调用COM对象的方法。

  • 作为一个链接这个遗留系统和其他系统的API之间。

  • 使用的WinForm其在某些情况下,用户界面。

更直观,据我了解的组件:

More visually, as I understand the components :

* [大遗产在UNIFACE系统] * < STRONG> == [通信] ==> [C#库] == [托管API] ==> * [大EDM管理系统] *

现在的问题是:一个在这个C#库中的方法,需要很长时间才能运行我的应该的使异步!

The question is: One of the methods in this C# Library takes too long to run and I "should" make it asynchronous!

我已经习惯了C#中,但不是在所有的COM。我已经做了并发编程,但COM似乎有很多的复杂性添加到它和我所有的试验迄今结束或者:

I'm used to C#, but not to COM at all. I've already done concurrent programming, but COM seems to add a lot of complexity to it and all my trials so far end in either:


  • 与所有

  • 没有错误消息崩溃
  • 我的DLL只有部分工作(只显示其UI的一部分,然后再关闭),仍然没有给我在所有

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

I'm out of ideas and resources about how to handle threads within a COM dll, and I would appreciate any hint or help.

到目前为止,代码的最大部分,我已经改变了,使我的方法异步的:

So far, the biggest part of the code I've changed to make my method asynchronous :

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

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

Any hint or useful resource would be appreciated. Thank you.

更新1:

继答案,以下(特别是关于的SynchronizationContext ,和的这个例子)我能重构我的代码,并使得它的工作,但在C#中的另一个窗口应用程序调用时存在,而不是通过COM。
遗留系统遇到一个非常模糊的错误,当我调用该函数并没有给出任何关于飞机坠毁的任何细节。

Following answers and clues below (especially about the SynchronizationContext, and with the help of this example) I was able to refactor my code and making it to work, but only when called from another Window application in C#, and not through COM. The legacy system encounters a quite obscure error when I call the function and doesn't give any details about the crash.

更新2:

在我的临床试验最新更新:我设法让多线程工作时,呼叫从一个测试项目做,和不可以 UNIFACE系统的。
多次试验之后,我们倾向于认为,我们的传统系统不支持以及在其目前的配置多线程。但是,这不是问题的问题更多:)

Latest updates in my trials: I managed to make the multithreading work when the calls are made from a test project, and not from the Uniface system. After multiple trials, we tend to think that our legacy system doesn't support well multithreading in its current config. But that's not the point of the question any more :)

下面是代码的exerpt,似乎工作:

Here is a exerpt of the code that seems to work:

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服务和创建系统和服务之间的接口。它应该是更加可持续的。

We are now considering other solutions than modifying this COM assembly, like encapsulating this library in a Windows Service and creating an interface between the system and the service. It should be more sustainable..

推荐答案

这是很难讲不知道更多的细节,但这里有几个问题。

It is hard to tell without knowing more details, but there are few issues here.

您通过的BeginInvoke 执行另一个线程委托,但你不等待它。作为同时仍在执行远程调用它已经通过了你的 try\catch 块不会赶上什么。相反,你应该把 try\catch 块内的 AsyncComparedSearch

You execute the delegate on another thread via BeginInvoke but you don't wait for it. Your try\catch block won't catch anything as it has already passed while the remote call is still being executed. Instead, you should put try\catch block inside AsyncComparedSearch.

当你不等待远程方法的执行结束( EndInvoke会或通过回调),我不知道你是怎么处理的结果COM调用。我想那么,你从内部 AsyncComparedSearch 更新GUI。如果是这样,这是错误的,因为它是在另一个线程运行,你永远不应该从任何地方,但GUI线程更新界面 - 这将有崩溃或其他意外行为最有可能的结果。因此,你需要同步的GUI更新工作GUI线程。在的WinForms,你需要使用 Control.BeginInvoke 或其他方式(如(不Delegate.BeginInvoke混淆) SynchronizationContext的)同步代码GUI线程。我用类似这样:

As you don't wait for the end of the execution of remote method (EndInvoke or via callback) I am not sure how do you handle the results of the COM call. I guess then that you update the GUI from within AsyncComparedSearch. If so, it is wrong, as it is running on another thread and you should never update GUI from anywhere but the GUI thread - it will most likely result with a crash or other unexpected behavior. Therefore, you need to sync the GUI update work to GUI thread. In WinForms you need to use Control.BeginInvoke (don't confuse it with Delegate.BeginInvoke) or some other way (e.g. SynchronizationContext) to sync the code to GUI thread. I use something similar to this:

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



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

then I call it like this from any thread:

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



此外,阅读的对于一些注意事项这个答案

这篇关于让我的COM组件调用异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆