2013-03-11 5 views
10

私は現在の仕事でC#でコード化されたレガシーライブラリを維持する特権を "獲得"しただけです。私のCOMアセンブリを非同期で呼び出す

このDLL:

  • は選択の余地はなく、COMオブジェクトの呼び出しを持っていないのUnifaceで作られた大きなレガシーシステムのための方法を公開します。
  • このレガシーシステムと別のシステムのAPIとの間のリンクとして機能します。
  • UIのためにWinFormを使用することがあります。

私はコンポーネントを理解してより視覚的に、:

*[Big legacy system in Uniface]*== [COM] ==>[C# Library]== [マネージドAPI] ==>*[Big EDM Management System]*

を質問があります:このC#ライブラリのメソッドの1つが実行に時間がかかり、"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 
} 

任意のヒントや便利なリソースをいただければ幸いです。 ありがとうございます。

UPDATE 1:

は(特にSynchronizationContextについて、およびthis exampleの助けを借りて)以下の答えと手がかりに続いて、私は私のコードをリファクタリングすることができましたし、それが動作するようになっていますが、他から呼び出された場合にのみ、 COMではなく、C#でのウィンドウアプリケーション。 レガシーシステムでは、関数を呼び出すとかなり曖昧なエラーが発生し、クラッシュに関する詳細はわかりません。

UPDATE 2:私の試験で

最新のアップデート:私は、コールがテストプロジェクトから作られていたときに、マルチスレッドを動作させるために、管理、およびのUnifaceシステムからない。 複数の試行の後、私たちのレガシーシステムは現在の設定でうまくマルチスレッドをサポートしていないと考える傾向があります。しかし、それはそれ以上の質問のポイントではありません:)ここ

が動作しているようですコードの抜粋です:

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サービスのライブラリを開き、システムとサービスの間のインターフェイスを作成します。それはより持続可能でなければなりません。

+3

+1このよく組織化された質問です。 – 3yanlis1bos

+0

クラッシュする本当に小さなサンプルを提供できますか?私は本当にそれがクラッシュするために何をしているのかは本当にわかりません:)(あなたのせいか、スレッディングを処理できないレガシーシステムの場合) – Onkelborg

+0

例外は捕まえられない、どんなメッセージも含んでいませんか? –

答えて

2

詳細は分かりませんが、ここではほとんど問題はありません。

BeginInvoke経由で別のスレッドでデリゲートを実行しますが、待つことはありません。 try\catchブロックは、リモートコールがまだ実行されている間に既に通過したものをキャッチしません。代わりに、ブロックAsyncComparedSearchの中にブロックtry\catchを置く必要があります。

リモートメソッド(EndInvokeまたはコールバック経由)の実行が終了するのを待たずに、私はCOM呼び出しの結果をどのように処理するのか分かりません。あなたはAsyncComparedSearchの中からGUIを更新すると思います。そうであれば、それは間違っています。別のスレッドで実行されているため、GUIスレッド以外のどこからでもGUIを更新しないでください。クラッシュや予期しない動作が発生する可能性が高くなります。したがって、GUI更新作業をGUIスレッドに同期させる必要があります。 WinFormsでは、コードをGUIスレッドに同期させるためにControl.BeginInvoke(Delegate.BeginInvokeと混同しないでください)または他の方法(例えばSynchronizationContext)を使用する必要があります。私はこれに似たものを使用します。

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

のほかに、いくつかの注意点についてthis answerをお読みください。

+0

あなたの返信とリンクをありがとうございます。 AsyncComparedSearchのロジックはかなり複雑で、投稿には当てはまりません。私はそれに複数の 'try/catch'ブロックを持っており、何も捕まえていません。私は問題の編集に重要な細部を入れようとします。 GUIのハンドルについては正しいですが、これは 'AsyncComparedSearch'内から処理されます。私は今日その方向で検索し、あなたに知らせるでしょう。 – David

+0

答えに同期に関するメモを追加しました –

+0

あなたの答えと 'SynchronizationContext'に関するリンクの手がかりに続いて、私の関数を正しく動作させることができましたが、呼び出しが別のC#プロジェクトから行われたときだけ、 COM経由でレガシーシステムからの呼び出しが行われたときではありません。 少なくとも、ここには正の進化があります。 – David

関連する問題