Назвать VB6 DLL из многопоточного c# сервисного приложения окон?

Полезно в ситуациях, где Вы скрыли внутреннее состояние, такое как кэш. Например:

class HashTable
{
...
public:
    string lookup(string key) const
    {
        if(key == lastKey)
            return lastValue;

        string value = lookupInternal(key);

        lastKey = key;
        lastValue = value;

        return value;
    }

private:
    mutable string lastKey, lastValue;
};

И затем Вы можете иметь const HashTable, объект все еще использует lookup() метод, который изменяет внутренний кэш.

8
задан DaveInCaz 20 May 2019 в 12:28
поделиться

4 ответа

Когда потоки входят, вы сохраняете объекты и повторно используете их позже в новых потоках? Если можете, создавайте новые объекты для каждого потока. У нас есть такая ситуация с 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();
}
2
ответ дан 6 December 2019 в 00:58
поделиться

Вы говорите

Я использую многопоточные окна сервис, который нужно вызвать dll VB6. Об этом нет документации VB6 dll и эта устаревшая система поддерживает очень важный бизнес процесс.

и в то же время вы говорите

В первый раз (поток 1º) эта dll работает хорошо. По мере необходимости другим потокам доступ, он начинает предоставлять неправильный результаты.

Я был бы очень уверен, что руководство знает о сбое, которое вы наблюдаете, потому что код, поддерживающий критически важный бизнес-процесс, старый и недокументированный и используется таким образом, который никогда не был предназначен для использования, и никогда не тестировался для использования. Бьюсь об заклад, он также никогда не тестировался для использования из .NET, не так ли?

Вот мое предложение, и оно похоже на то, что я фактически реализовал:

DLL VB6 ожидает вызова на одном нить. Не разочаровывайте! Когда ваша служба запускается, пусть она запускает поток соответствующего типа (я не могу сказать, так как я намеренно забыл все эти STA / MTA). Поставьте в очередь запросы к этому потоку для доступа к VB6 DLL. Весь такой доступ должен проходить через единственный поток.

Таким образом, что касается VB6 DLL, он работает точно так же, как был протестирован.


Кстати, это немного отличается от того, что я реализовал. У меня была веб-служба, а не служба Windows. У меня была C DLL, а не VB6, и это не был COM. Я просто реорганизовал весь доступ к этому объекту в один класс, а затем поместил операторы блокировки вокруг каждого из общедоступных методов.

1
ответ дан 6 December 2019 в 00:58
поделиться

This article on multithreading Visual Basic 6 DLL's provides some insight. It says:

To make an ActiveX DLL project многопоточность, выберите нужный параметры потоковой передачи на вкладке Общие диалогового окна Project Properties.

В этой статье говорится, что есть три возможных модели на выбор:

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

Я предполагаю, что по умолчанию один поток выполнения , и что одна из необходимо выбрать два других параметра.

0
ответ дан 6 December 2019 в 00:58
поделиться

Вы можете взглянуть на это: linky

И вот фрагмент, который привлек мое внимание:

COM-объекты VB6 являются объектами STA, это означает, что они должен работать в потоке STA. Вы создали два экземпляра объекта из двух потоков MTA, но сам объект будет работать на одном (созданном COM (OLE)) STA поток, и доступ из двух потоков MTA будет маршалирован и синхронизирован. Итак, что вам следует сделать, это инициализировать потоки как STA, чтобы каждый объект работал в своем собственном потоке STA без маршалинга, и вы будет хорошо.

В любом случае COM-объекты стиля VB всегда являются STA. Теперь, чтобы предотвратить маршалинг квартир и переключение потоков, вам нужно создать экземпляры в квартирах, инициализированных STA. Также обратите внимание, что когда вы устанавливаете атрибут [MTAThread] в Main, вы эффективно инициализируете основной поток как MTA, когда вы создаете экземпляры объектов STA из потоков MTA COM создаст отдельный (неуправляемый) поток и инициализирует его как STA (это называется по умолчанию STA), все вызовы объектов STA из потоков MTA будут маршалироваться (и включать переключение потоков), в некоторых случаях вызовы Idispatch завершится ошибкой из-за сбоев маршалинга IP. Поэтому рекомендуется использовать объекты STA (и, следовательно, VB6) только из совместимых квартир.

0
ответ дан 6 December 2019 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: