簡體   English   中英

從多線程c#Windows服務應用程序中調用VB6 DLL?

[英]Call VB6 DLL from a multithreaded c# windows service application?

我正在運行需要調用VB6 dll的多線程Windows服務。 沒有有關此VB6 dll的文檔,並且該舊系統支持非常關鍵的業務流程。

第一次(第一個線程),該dll表現良好。 由於其他線程需要訪問,因此它開始提供錯誤的結果。

我讀過一個人說:

“如果要使用VB6,請小心一件事。如果要運行多線程服務,則必須更改線程模型以支持單元。VB僅支持多個單線程單元,但是.NET通常會運行完全免費的線程。調用VB6 DLL的線程必須與DLL兼容。”

團隊中的另一個人給了我這個將DDL放在單獨的應用程序域中的想法。 但是我不確定。

我們如何使用從多線程C#Windows Service應用程序調用的VB6 dll?

當線程進入時,您是否要保存對象並稍后在新線程上重用它們? 如果可以,請為每個線程新鮮創建對象。 我們使用的數據層dll存在這種情況。 如果在一個線程上創建連接,則無法從另一個線程使用該連接。 如果在每個線程上創建一個新的連接,它將正常工作。

如果創建對象的速度很慢,請查看ThreadPool類和ThreadStatic屬性。 線程池反復循環使用同一組線程來完成工作,而ThreadStatic允許您創建一個僅存在於一個線程中的對象。 例如

[ThreadStatic]
public static LegacyComObject myObject;

當有請求進入時,將其轉換為作業並將其放入線程池中。 作業開始時,檢查靜態對象是否已初始化;

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

    // now do the work against myObject
    myObject.DoGreatStuff();
}

你說

我正在運行需要調用VB6 dll的多線程Windows服務。 沒有有關此VB6 dll的文檔,並且該舊系統支持非常關鍵的業務流程。

同時你說

第一次(1º線程)時,此dll性能良好。 由於其他線程需要訪問,因此它開始提供錯誤的結果。

我非常確定管理層會意識到您所遇到的失敗,因為支持關鍵業務流程的代碼是舊的且沒有文檔記錄,並且正在以從未打算使用且未經測試的方式使用使用。 我敢打賭,它也從未經過過.NET的使用測試,對嗎?

這是我的建議,這與我實際執行的類似:

VB6 DLL期望在單個線程上被調用。 不要失望! 當您的服務啟動時,讓它啟動適當類型的線程(我不能說,因為我故意忘記了所有STA / MTA東西)。 將對該線程的請求排隊,以訪問VB6 DLL。 使所有此類訪問都通過單線程。

這樣,就VB6 DLL而言,它的運行與經過測試可運行的完全相同。


順便說一句,這與我已經實現的略有不同。 我有一個Web服務,而不是Windows服務。 我有一個C DLL,而不是VB6,它不是COM。 我只是將對事物的所有訪問重構為一個類,然后在每個公共方法周圍放置鎖語句。

這篇有關多線程Visual Basic 6 DLL的文章提供了一些見解。 它說:

若要使ActiveX DLL項目成為多線程,請在“項目屬性”對話框的“常規”選項卡上選擇所需的線程選項。

本文說,有三種可能的模型可供選擇:

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

我假設默認值是one thread of execution ,並且需要選擇其他兩個選項之一。

您可能需要看一下: linky

以下是引起我注意的摘要:

VB6 COM對象是STA對象,這意味着它們必須在STA線程上運行。 您確實從兩個MTA線程創建了對象的兩個實例,但是對象本身將在單個(COM(OLE)創建的)STA線程上運行,並且將對來自兩個MTA線程的訪問進行封送和同步。 因此,您應該做的是,將線程初始化為STA,以便每個對象都在自己的STA線程上運行,而不會封送處理,這樣就可以了。

無論如何,VB樣式的COM對象始終是STA。 現在,為了防止單元封送和線程切換,您需要在STA初始化的單元中創建實例。 還要注意,在Main上設置[MTAThread]屬性時,可以將主線程有效地初始化為MTA,當您從MTA線程創建STA對象的實例時,COM將創建一個單獨的(非托管)線程並將其初始化為STA(這是稱為默認STA),則將從MTA線程對STA對象的所有調用進行封送處理(並引發線程切換),在某些情況下,由於IP封送處理故障,Idispatch調用將失敗。 因此,建議僅使用兼容公寓中的STA(因此使用VB6)對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM