TThread :: Queue аварийно завершает работу C ++ Builder - PullRequest
0 голосов
/ 20 сентября 2019

Я использую C ++ Builder 2010. У меня есть вызов TThread::Synchronize, который прекрасно работает - функция потока вызывает Synchronize, и это хорошо.Однако, если я заменю его на TThread::Queue, он сразу же вылетает.

Есть ли какая-то конкретная ошибка в этой версии C ++ Builder или что-то еще происходит?

Это функция, которую я используюЧтобы вызвать функцию основного потока:

void RunInMainThread(void(__closure *FuncToCall)(const __int64, const wchar_t), const __int64 fP1, const wchar_t fP2)
{
struct
    {
    private: typedef void(__closure *FTCdef)(const __int64, const wchar_t);

    public: __int64 P1;
            wchar_t P2;
            FTCdef  FTC;

            void __fastcall ExecFunc()
                {
                FTC(P1,P2);
                }
    } Args = { fP1, fP2, FuncToCall };

TThread::Synchronize(NULL, &Args.ExecFunc);
//TThread::Queue    (NULL, &Args.ExecFunc);
}

Функция, которую она вызывает, действительно очень проста, она просто обновляет панель инструментов с некоторым текстом, может быть, 2-3 строками кода.

1 Ответ

1 голос
/ 21 сентября 2019

TThread::Queue() работает асинхронно .Метод, который вы передаете ему, помещается во внутреннюю очередь, а затем TThread::Queue() немедленно завершается.Основной поток пользовательского интерфейса запускает метод очереди как можно раньше, обычно спустя много времени после того, как поток очереди переходит к другим действиям.

Метод, который вы передаете TThread::Queue(), принадлежит переменной, локальной дляRunInMainThread(), он выходит из области видимости и больше не действителен к моменту вызова метода из очереди.Вот почему ваш код дает сбой.

У вас нет этой проблемы с TThread::Synchronize(), потому что он запускает синхронно , он не завершается, пока не будет вызван синхронизированный метод.Таким образом, можно использовать метод, принадлежащий локальной переменной, переменная не выйдет из области видимости до тех пор, пока не завершится синхронизированный метод.

Чтобы исправить использование TThread::Queue(), вам необходимодинамически выделяйте переменную и позволяйте основному потоку пользовательского интерфейса освободить ее после выполнения метода в очереди, например:

typedef void (__closure *FTCdef)(const __int64, const wchar_t);

void RunInMainThread(FTCdef FuncToCall, const __int64 fP1, const wchar_t fP2)
{
    struct Args
    {
        __int64 P1;
        wchar_t P2;
        FTCdef FTC;

        /*
        void __fastcall ExecFuncSync()
        {
            FTC(P1, P2);
        }
        */

        void __fastcall ExecFuncQueue()
        {
            try {
                FTC(P1, P2);
            } __finally {
                delete this;
            }
        }
    };

    //Args args{fP1, fP2, FuncToCall};
    //TThread::Synchronize(NULL, &args.ExecFuncSync);

    Args *args = new Args;
    args->P1 = fP1;
    args->P2 = fP2;
    args->FTC = FuncToCall;
    TThread::Queue(NULL, &args->ExecFuncQueue);
}
...