Using C++ Builder and the MainUI thread for feedback

56 Views Asked by At

I have a simple question about where to use synchronization when communicating with the user through a Main Form in a multi-threaded application.

I've learned that in multi-threaded apps, to give feedback to the user, we must synchronize before the use of visual components on the Main UI thread .

The way I've done it for this project is to have a method in my MainForm called Log. The member FNow is a date string created in the MainForm ctor and updated in a TTimer. Likewise the FLogFile member is created in the ctor, and is a unique_ptr<TBufferedFileStream>. Here's the code for the MainForm->Log(Str) method.

//---------------------------------------------------------------------------
void __fastcall TMainForm::Log(String logStr)
{
    TThread::Queue( NULL, [ this, logStr ]() {  
    String nowLog = "[" + FNow + "]: " + logStr;
            if( ShowLogChk->Checked )
                Memo->Lines->Append( nowLog );
        FLogFile->Write(nowLog.BytesOf() , nowLog.Length());
    });
}

The MainForm->Log() method is called from various other objects including inside of TTask's and may possibly be called in a TThread, really anywhere I need to give feedback to the user. For example, this is how it's currently used.

_di_ITask FetchTask = TTask::Create([this, AKey]()
{
    MainForm->Log("Widget Task is starting...");
    SomeObject->CreateNewWddiget(qryFDQuery, AKey);
});
FetchTask->Start();

My question is, does anyone see an issue with doing it this way, or would it be better to Queue the call where it is used, for example?

void __fastcall TSomeClass::AlertMainForm(String str)
{
    TThread::Queue(NULL, [this, str]() {    
        MainForm->Memo->Lines->Add("Alerting main form: " + str);
    });
}

If do it 2nd way, I'm reusing the same code multiple times and creating more chances of bugging out?

0

There are 0 best solutions below