C # Лучший подход для отзывчивого интерфейса во время запроса SQL с использованием взаимодействия COM - PullRequest
0 голосов
/ 26 ноября 2009

Я делаю плагин C # DLL для EXE, написанный на VB6. У меня нет доступа к источнику EXE. Сама DLL работает и прекрасно взаимодействует с EXE.

Вот процесс для события:

  1. Пользователь выдает команду на EXE, которая затем вызывает функцию в DLL, передавая объект в качестве параметра
  2. DLL обрабатывает данные, которые иногда занимают много времени
  3. DLL отвечает, вызывая функцию переданного объекта. Сама функция DLL ничего не возвращает

    public void DoCommand(object CommandSettings)
    {
        //ObjectVB6 is my custom class to allow easy calling of COM methods and properties
        ObjectVB6 CS = new ObjectVB6(CommandSettings);
        ... //process data
        CS.CallMethod("MyReply", args);
    }
    

Моя проблема в том, что во время длинных запросов (из DLL) пользовательский интерфейс EXE зависает.

Каков наилучший способ предотвратить это? Я пытался использовать асинхронные запросы MySQL, которые были бесполезны, и пытался использовать несколько потоков, которые просто сталкиваются с проблемами защищенной памяти.

Любой совет, который вы можете дать, был бы потрясающим. Я пытался решить эту проблему в течение нескольких дней. Благодаря.

Ответы [ 5 ]

1 голос
/ 27 ноября 2009

Попробуйте следующее:

BackgroundWorker bw = null; 
ObjectVB6 CS = null;

public void DoCommand(object CommandSettings)
{
    //ObjectVB6 is my custom class to allow easy calling of COM methods and properties
    CS = new ObjectVB6(CommandSettings);

    // hook up background worker
    bw = new BackgroundWorker();
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}

private void bw_DoWork(...)
{
    // process data, e.g. the piece that takes too long
}

private void bw_RunWorkerCompleted
{
   CS.CallMethod("MyReply", args);
}

Как сказал один из респондентов, это может работать, а может и не работать из-за особенностей резьбы в квартирах VB6.

0 голосов
/ 27 ноября 2009

Я придумала способ достичь того, что я хотела. Хотя я бы предпочел более приятный метод, этот способ работает.

Использовал две очереди для обмена информацией. Основной поток прослушивает получение очереди _get и устанавливает очередь _set при выполнении запроса. Рабочий поток просто вставляет запрос в очередь _get и ждет, пока _set будет готов. Основной поток просто действует как прокси.

Спасибо за вашу помощь!

0 голосов
/ 26 ноября 2009

IMO, лучший способ справиться с этим - перевести ваш запрос в ThreadPool на стороне DLL, стиль «запускай и забывай». Вы пробовали это?

В противном случае вам придется подключить функцию обратного вызова к вашей программе VB6, чтобы получить статус, который, как вы, возможно, уже обнаружили, является хитрым из-за модели однопотоковой квартиры VB6.

Если вы хотите глубже изучить опасности и преимущества многопоточности в VB6, взгляните на следующую статью. Это может позволить вам просто запустить поток и сделать это на стороне VB6:

Многопоточность в VB5 и VB6
http://www.freevbcode.com/ShowCode.Asp?ID=1287

0 голосов
/ 27 ноября 2009

Все функции, разработанные в .NET, можно вызывать асинхронно с использованием делегата, а затем вызывать BeginInvoke для фактического вызова функции. Поскольку ваша функция ничего не возвращает, вам не нужно вызывать EndInvoke. Используя IAsyncResult, вы можете выполнить требование обратного вызова. Хорошим справочником о том, как сделать это правильно, является «Программирование компонентов .NET» Джувала Лоуи, опубликованное O'Reilly. ISBN - 0596102070. Удачи.

0 голосов
/ 26 ноября 2009

Почему вы не можете просто использовать рабочий поток для этого кода? С какими "проблемами защищенной памяти" вы сталкиваетесь?

...