8

VB6dllを呼び出す必要があるマルチスレッドWindowsサービスを実行しています。このVB6dllに関するドキュメントはなく、このレガシーシステムは非常に重要なビジネスプロセスをサポートしています。

初めて(最初のスレッド)、このdllはうまく機能します。他のスレッドがアクセスする必要があるため、間違った結果を提供し始めます。

私は言っている一人の男を読んだ:

「VB6を使用している場合は、1つだけ注意してください。マルチスレッドサービスを実行している場合は、スレッドモデルを変更してアパートメントをサポートする必要があります。VBは複数のシングルスレッドアパートメントのみをサポートしますが、.NETは通常は完全にフリースレッドで実行されます。VB6DLLを呼び出すスレッドは、DLLと互換性がある必要があります。」

チームの別の人が、このddlを別のアプリケーションドメインに配置するというアイデアをくれました。確信はないけど。

マルチスレッドのc#Windowsサービスアプリケーションから呼び出されたVB6 dllをどのように操作できますか?

4

4 に答える 4

2

スレッドが入ってくると、オブジェクトを保存して、後で新しいスレッドで再利用しますか?可能であれば、すべてのスレッドに対して新しいオブジェクトを作成します。使用するデータレイヤーdllでこのような状況が発生します。あるスレッドで接続を作成した場合、別のスレッドからは使用できません。各スレッドで新しい接続を作成すると、正常に機能します。

オブジェクトの作成に時間がかかる場合は、ThreadPoolクラスとThreadStatic属性を確認してください。スレッドプールは、同じスレッドのセットを何度もリサイクルして作業を行います。ThreadStaticを使用すると、1つのスレッドにのみ存在するオブジェクトを作成できます。例えば

[ThreadStatic]
public static LegacyComObject myObject;

リクエストが届いたら、それをジョブに変換し、スレッドプールにキューに入れます。ジョブが開始したら、静的オブジェクトが初期化されているかどうかを確認します。

void DoWork()
{ 
    if (myObject == null)
    { 
        // slow intialisation process
        myObject = New ...
    }

    // now do the work against myObject
    myObject.DoGreatStuff();
}
于 2009-07-03T21:55:14.973 に答える
1

あなたは言う

VB6dllを呼び出す必要があるマルチスレッドWindowsサービスを実行しています。このVB6dllに関するドキュメントはなく、このレガシーシステムは非常に重要なビジネスプロセスをサポートしています。

同時にあなたは言う

最初は(1ºスレッド)、このdllはうまく機能します。他のスレッドがアクセスする必要があるため、間違った結果を提供し始めます。

重要なビジネスプロセスをサポートするコードは古く、文書化されておらず、意図されていない方法で使用されており、テストされていないため、管理者はあなたが見ている失敗を認識していることを確信しています。利用される。.NETからの使用もテストされたことがないのではないでしょうか。

これが私の提案です。これは私が実際に実装したものと似ています。

VB6 DLLは、シングルスレッドで呼び出されることを想定しています。がっかりしないでください!サービスが開始したら、適切なタイプのスレッドを起動してもらいます(STA / MTAのすべてを意図的に忘れてしまったため、言えません)。VB6 DLLにアクセスするために、そのスレッドへの要求をキューに入れます。そのようなすべてのアクセスが単一のスレッドを経由するようにします。

そうすれば、VB6 DLLに関する限り、実行がテストされたとおりに実行されます。


ところで、これは私が実装したものとは少し異なります。私はWindowsサービスではなくWebサービスを持っていました。私はVB6ではなくCDLLを持っていましたが、それはCOMではありませんでした。Thingへのすべてのアクセスを1つのクラスにリファクタリングしてから、各パブリックメソッドの周りにlockステートメントを配置しました。

于 2009-07-04T01:57:16.170 に答える
0

Visual Basic 6 DLLのマルチスレッドに関するこの記事は、いくつかの洞察を提供します。それは言う:

ActiveX DLLプロジェクトをマルチスレッドにするには、[プロジェクトのプロパティ]ダイアログボックスの[全般]タブで目的のスレッドオプションを選択します。

この記事では、次の3つのモデルから選択できると述べています。

One thread of execution 
Thread pool with round-robin thread assignment 
Every externally created object is on its own thread 

one thread of executionデフォルトはであり、他の2つのオプションのいずれかを選択する必要があると想定しています。

于 2009-07-03T20:52:56.533 に答える
0

あなたはこれを見てみたいかもしれません:linky

そして、これが私の注意を引いたスニペットです:

VB6 COMオブジェクトはSTAオブジェクトです。つまり、STAスレッドで実行する必要があります。2つのMTAスレッドからオブジェクトの2つのインスタンスを作成しましたが、オブジェクト自体は単一の(COM(OLE)作成された)STAスレッドで実行され、2つのMTAスレッドからのアクセスはマーシャリングおよび同期されます。したがって、スレッドをSTAとして初期化して、各オブジェクトがマーシャリングせずに独自のSTAスレッドで実行されるようにする必要があります。

とにかく、VBスタイルのCOMオブジェクトは常にSTAです。ここで、アパートメントのマーシャリングとスレッドの切り替えを防ぐために、STAで初期化されたアパートメントにインスタンスを作成する必要があります。Mainで[MTAThread]属性を設定すると、メインスレッドをMTAとして効果的に初期化することにも注意してください。MTAスレッドからSTAオブジェクトのインスタンスを作成すると、COMは別の(管理されていない)スレッドを作成し、それをSTAとして初期化します(これはデフォルトのSTAと呼ばれます)、MTAスレッドからSTAオブジェクトへのすべての呼び出しがマーシャリングされ(スレッドスイッチが発生し)、場合によっては、IPマーシャリングの失敗が原因でIdispatch呼び出しが失敗します。したがって、互換性のあるアパートメントのSTA(したがってVB6)オブジェクトのみを使用することをお勧めします。

于 2009-07-03T21:05:37.350 に答える