TIdHTTP::OnAuthorization in multithreaded application - multithreading

I'm writing a DLL in C++Builder XE6 to communicate with a REST server. The DLL creates a TThread-derived thread to do GET requests in the background, using TIdHTTP. The DLL also exports functions to do GET and POST requests in the main thread, using a second TIdHTTP instance. Both TIdHTTP instances can trigger an OnAuthorization event if the server returns a 401 (Unauthorized) response code.
I've written a function to prompt the user for credentials, called PromptForCredentials(), which shows a standard Windows credentials dialog. This function is called if either instance triggers an OnAuthorization event (in the background thread via Synchronize()). Only thing is, the background thread can trigger an OnAuthorization event while the user is being prompted for credentials during an OnAuthorization event in the main thread and vice versa. This would show two copies of the credentials dialog at the same time.
I can use TCriticalSection to prevent calling PromptForCredentials() twice, so that only one copy of the credentials dialog is shown at a time. That way, if the main thread prompts for credentials, the background thread will block when it also tries to prompt for credentials and vice versa.
If authentication is successful in one thread, the other thread should use the same credentials instead of prompting the user a second time. I can do this by copying the Username and Password properties from one TIdHTTP instance to the other, either at the end of the OnAuthorization event or after the request is completed. However, if a second OnAuthorization event occurs during the first one, the user is still prompted twice for credentials. AFAIK, TCriticalSection doesn't provide a way to check if the lock is already acquired. Otherwise, I could wait until the lock is released and use the credentials without prompting a second time.
How do I prevent prompting the user for credentials twice in succession?
Update
The documentation for TMultiReadExclusiveWriteSynchronizer::BeginWrite() states:
As a rule, a thread should always discard previous samples from
protected memory after promoting a read lock to a write lock. However,
the calling thread can determine whether a state change has occurred
by examining return value of BeginWrite: True if the protected memory
has not been written to by another thread or False if another thread
may have modified the protected memory.
So, here's what I tried:
#include <System.SysUtils.hpp>
TMultiReadExclusiveWriteSynchronizer* Lock = NULL;
void GetCreds (const String Caption)
{
Lock->BeginRead();
try
{
// Retrieve globally stored credentials here.
bool Prompt = Lock->BeginWrite();
try
{
if (Prompt)
Application->MessageBox(_T("Prompt"), Caption.c_str(), MB_OK);
else
Application->MessageBox(_T("Use"), Caption.c_str(), MB_OK);
}
__finally
{
Lock->EndWrite();
}
}
__finally
{
Lock->EndRead();
}
}
class TMyThread : public TThread
{
typedef TThread inherited;
protected:
void __fastcall DoTask ();
virtual void __fastcall Execute ();
public:
__fastcall TMyThread () : inherited(true) {}
};
void __fastcall TMyThread::DoTask ()
{
GetCreds("Thread");
}
void __fastcall TMyThread::Execute ()
{
while (!Terminated)
{
Sleep(2000);
if (Terminated)
break;
Synchronize(DoTask);
}
}
void __fastcall TForm1::Button1Click (TObject *Sender)
{
Lock = new TMultiReadExclusiveWriteSynchronizer();
try
{
TMyThread* Thread = new TMyThread();
try
{
Thread->Start();
GetCreds("Main");
}
__finally
{
Thread->Terminate();
Thread->WaitFor();
delete Thread;
}
}
__finally
{
delete Lock;
}
}
When I click Button1, I get a message box with caption "Main" and text "Prompt". As expected, the user is prompted for credentials the first time.
With the message box still open, the background thread kicks in after 2 seconds with a (synchronized) call to GetCreds(). Since the main thread acquired a write lock, you would expect the background thread to be blocked on the BeginRead() call and no second message box to appear. However, I still get a second message box with caption "Thread" and text "Prompt".
To test, I switched from TMultiReadExclusiveWriteSynchronizer to TCriticalSection.
GetCreds() now looks like this:
void GetCreds (const String Caption)
{
Lock->Acquire();
try
{
Application->MessageBox(_T("Prompt"), Caption.c_str(), MB_OK);
}
__finally
{
Lock->Release();
}
}
I still get two message boxes, while I should only see the one from the main thread.
What am I doing wrong?
Update 2
As Remy pointed out, TCriticalSection locks are reentrant for the thread that has the lock. If I call GetCreds() directly in the thread, i.e. without Synchronize(), the code in my first update works as expected.
I also found that TCriticalSection has a TryEnter() method, whose return value can be used to check if another thread currently has the lock.

Related

Qt Blocking thread until condition met

class Driver : Public QObject
{
Q_OBJECT
private:
// method command: sends a command
// signal ok: command executed, sends back a message
MyDevice *device;
public:
Deriver()
{
device = new MyDevice(0);
connect (mydevice,&MyDevice::ok,this,&Driver::onInitOk);
}
public slots:
void init()
{
device->command("init");
//at this point, I want to block this method until the device signals ok with a given msg
}
command()
{
device->command("setmode x");
device->command("cmd");
//at this point, I want to block this method until the device signals ok with a given msg
}
void onInitOk(QString msg)
{
//somehow unblock the actually running command, if the msg matches
}
}
I would like to use the command/init with a QueuedConnection, so they are executed async from the gui thread, and sequentially. (Am I right?)
How can I implement the blocking effectively?
Okay so I've edited based on the clarity of the comments given. The best place to look at would be the Qt Threading Guide. This can give a much better breakdown on the systems used for concurrency.
For your example I've added a QMutex object to your Driver class. It may be worth thinking about if you want to move the thread-based controls into the MyDevice class itself if you have access.
Driver()
{
moveToThread(new QThread());
device = new MyDevice(0);
}
void init()
{
mutex.lock();
const QString& result = device->command("init");
onInitOk(result);
}
void command()
{
mutex.lock();
device->command("setmode x");
const QString& result = device->command("cmd");
onInitOk(result);
}
void onInitOk(QString msg)
{
...[STUFF]
// Even when things go wrong you MUST unlock the mutex at some point.
// You can't keep the thread blocked forever in cases of poor results.
// As such it might be better practice to unlock in
// the same function that locks!
mutex.unlock();
}
QMutex mutex;
Bear in mind I am assuming you are wanting to access the functionality from the slots mechanism. Hence why we use the moveToThead() function. When the object is accessed via slots in the GUI thread it'll now run the function on a different thread.
Likewise the mutex only blocks for all the objects that share that one mutex instance. So depending on your implementation you may have to think about what is right for you in exposing that mutex.

Scrollbar messages block interthread messages in MFC

I have an MFC application which is composed of multiple threads, but the problem is with a specific two.
The first thread (CGuiThread) is responsible for GUI (it's not the main thread) and contains a window object (CMainWindow), which contains an inner window object (CInnerWindow), which displays multiple progress displays and has a scroll bar.
The second thread (CStatusDispatcherThread) is responsible for sending to the gui thread messages, which contain progress status information related to some calculation processes.
Once the calculations begin, the status dispatcher sends messages with the status to the GUI thread. The gui thread updates progress bars in the inner window accordingly.
The problem starts when I move or hold the thumb of the inner window's scroll bar - it seems that GUI thread stops processing the status messages from the status dispatcher thread, since the progress bars are no longer updated. Not only that, I'd expect the status messages to be stopped somewhere and processed once I release the tumb, but it is not happening. New messages arrive but the messages that while clicking are lost.
If anyone has an idea what could be the cause, I would be very grateful.
I tried "catching" the status messages in the CGuiThread::PreaTranslateMessage function, but it seems that after holding the scroll thumb, they no longer get there, even though PostThreadMessage of CStatusDispatcherThread indicates they were sent successfully.
#define MY_MESSAGE 1
class CStatusDispatcherThread : public CWinThread
{
//...
// This class sends progress status percentaget to gui thread via PostThreadMessage
OnTimer(UINT nIDEvent)
{
PostThreadMessage(iThreadID,MY_MESSAGE,100,0);
}
};
class CGuiThread : public CWinThread
{
//...
BEGIN_MESSAGE_MAP(CGuiThread, CWinThread)
ON_THREAD_MESSAGE(MY_MESSAGE,OnStatusMessage)
END_MESSAGE_MAP()
private:
CMyMainWindow m_mainWindow;
void OnStatusMessage(WPARAM iStatus, LPARAM dummy);
{
m_mainWindow.updateStatus((int)iStatus)
}
};
class CMyMainWindow : public CWnd
{
//...
void updateStatus(int iStatus)
{
m_sbarWindow.updateStatusBar(iStatus);
}
private:
CInnerWindow m_sbarWindow;
};
class CInnerWindow : public CWnd
{
//...
void updateStatusBar(int iStatus)
{
//...
}
private:
BOOL Create(...)
{
CWnd::Create(strClassName, strWindowTitle, WS_DLGFRAME | WS_CHILD| WS_VISIBLE | WS_VSCROLL,
rectRectOfWnd, pParentWnd, iID, NULL);
}
void OnVScroll(nSBCode, nPos, pScrollBar)
{
//...
}
};
Thank in advance,
Gal
It is documented to fail. From the MSDN page on PostThreadMessage:
if the recipient thread is in a modal loop (as used by MessageBox or
DialogBox), the messages will be lost.
Holding down the scroll slider creates such a modal loop. You can eliminate the problem by posting to an HWND, not to a thread ID.
The only thread that is allowed to update the GUI is the main thread. Otherwise you'll end up with unpredicted behavior.

Simplifying VCL thread wrapper code

I am using thread wrapper which checks if function which updates VCL (which also has some arguments) was called from main thread or not and then executes in within the context of Main thread always.
It works but I want to make it simpler. The problem is that I have to repeat this code in every function which needs VCL synchronization which is prone to errors. Is there a way to make this wrapper simpler and more re-useable? Note that this particular wrapper only uses one parameter but there can be any number of parameters which are copied to TLocalArgs and passed on.
Current code:
boost::scoped_ptr<TIdThreadComponent> WorkerThread;
...
void TForm1::SetMemoMessage(UnicodeString Msg)
{
// Check which thread called function, main thread or worker thread
if (GetCurrentThreadId() != System::MainThreadID)
{
struct TLocalArgs
{
TForm1 *Form;
UnicodeString Msg;
void __fastcall SetMemoMessage() // Same name as main function to make it easier to maintain
{
// We are in main thread now, safe to call message update directly
Form->SetMemoMessage(Msg);
}
};
// We are in worker thread, wrap into Synchronize
TLocalArgs Args = { this, Msg };
WorkerThread->Synchronize(&Args.SetMemoMessage);
return;
}
// MAIN THREAD CODE is very simple compared to wrapper above
Memo1->Text = Msg;
}
TThread::Synchronize() checks MainThreadID internally for you and calls the specified procedure directly if Synchronize() is called from the main thread. So just call Synchronize() unconditionally and let it handle the details. Synchronize() also has overloaded static versions available so you don't even need a TThread pointer to call it.
Try this:
void TForm1::SetMemoMessage(UnicodeString Msg)
{
struct TLocalArgs
{
UnicodeString Msg;
void __fastcall SetMemoMessage()
{
Form1->Memo1->Text = Msg;
}
};
TLocalArgs Args;
Args.Msg = Msg;
TThread::Synchronize(NULL, &Args.SetMemoMessage);
}

Modify Qt GUI from background worker thread

I work in Qt and when I press the button GO I need to continuously send packages to the network and modify the interface with the information I receive.
The problem is that I have a while(1) in the button so the button never finishes so the interface is never updated. I thought to create a thread in the button and put the while(){} code there.
My question is how can I modify the interface from the thread? (For example how can I modify a textBox from the thread ?
Important thing about Qt is that you must work with Qt GUI only from GUI thread, that is main thread.
That's why the proper way to do this is to notify main thread from worker, and the code in main thread will actually update text box, progress bar or something else.
The best way to do this, I think, is use QThread instead of posix thread, and use Qt signals for communicating between threads. This will be your worker, a replacer of thread_func:
class WorkerThread : public QThread {
void run() {
while(1) {
// ... hard work
// Now want to notify main thread:
emit progressChanged("Some info");
}
}
// Define signal:
signals:
void progressChanged(QString info);
};
In your widget, define a slot with same prototype as signal in .h:
class MyWidget : public QWidget {
// Your gui code
// Define slot:
public slots:
void onProgressChanged(QString info);
};
In .cpp implement this function:
void MyWidget::onProgressChanged(QString info) {
// Processing code
textBox->setText("Latest info: " + info);
}
Now in that place where you want to spawn a thread (on button click):
void MyWidget::startWorkInAThread() {
// Create an instance of your woker
WorkerThread *workerThread = new WorkerThread;
// Connect our signal and slot
connect(workerThread, SIGNAL(progressChanged(QString)),
SLOT(onProgressChanged(QString)));
// Setup callback for cleanup when it finishes
connect(workerThread, SIGNAL(finished()),
workerThread, SLOT(deleteLater()));
// Run, Forest, run!
workerThread->start(); // This invokes WorkerThread::run in a new thread
}
After you connect signal and slot, emiting slot with emit progressChanged(...) in worker thread will send message to main thread and main thread will call the slot that is connected to that signal, onProgressChanged here.
P.s. I haven't tested the code yet so feel free to suggest an edit if I'm wrong somewhere
So the mechanism is that you cannot modify widgets from inside of a thread otherwise the application will crash with errors like:
QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
Segmentation fault
To get around this, you need to encapsulate the threaded work in a class, like:
class RunThread:public QThread{
Q_OBJECT
public:
void run();
signals:
void resultReady(QString Input);
};
Where run() contains all the work you want to do.
In your parent class you will have a calling function generating data and a QT widget updating function:
class DevTab:public QWidget{
public:
void ThreadedRunCommand();
void DisplayData(QString Input);
...
}
Then to call into the thread you'll connect some slots, this
void DevTab::ThreadedRunCommand(){
RunThread *workerThread = new RunThread();
connect(workerThread, &RunThread::resultReady, this, &DevTab::UpdateScreen);
connect(workerThread, &RunThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
The connection function takes 4 parameters, parameter 1 is cause class, parameter 2 is signal within that class. Parameter 3 is class of callback function, parameter 4 is callback function within the class.
Then you'd have a function in your child thread to generate data:
void RunThread::run(){
QString Output="Hello world";
while(1){
emit resultReady(Output);
sleep(5);
}
}
Then you'd have a callback in your parent function to update the widget:
void DevTab::UpdateScreen(QString Input){
DevTab::OutputLogs->append(Input);
}
Then when you run it, the widget in the parent will update each time the emit macro is called in the thread. If the connect functions are configured properly, it will automatically take the parameter emitted, and stash it into the input parameter of your callback function.
How this works:
We initialise the class
We setup the slots to handle what happens with the thread finishes and what to do with the "returned" aka emitted data because we can't return data from a thread in the usual way
we then we run the thread with a ->start() call (which is hard coded into QThread), and QT looks for the hard coded name .run() memberfunction in the class
Each time the emit resultReady macro is called in the child thread, it's stashed the QString data into some shared data area stuck in limbo between threads
QT detects that resultReady has triggered and it signals your function, UpdateScreen(QString ) to accept the QString emitted from run() as an actual function parameter in the parent thread.
This repeats every time the emit keyword is triggered.
Essentially the connect() functions are an interface between the child and parent threads so that data can travel back and forth.
Note: resultReady() does not need to be defined. Think of it as like a macro existing within QT internals.
you can use invokeMethod() or Signals and slots mechanism ,Basically there are lot of examples like how to emit a signal and how to receive that in a SLOT .But ,InvokeMethod seems interesting .
Below is example ,where it shows How to change the text of a label from a thread:
//file1.cpp
QObject *obj = NULL; //global
QLabel *label = new QLabel("test");
obj = label; //Keep this as global and assign this once in constructor.
Next in your WorkerThread you can do as below:
//file2.cpp (ie.,thread)
extern QObject *obj;
void workerThread::run()
{
for(int i = 0; i<10 ;i++
{
QMetaObject::invokeMethod(obj, "setText",
Q_ARG(QString,QString::number(i)));
}
emit finished();
}
you start thread passing some pointer to thread function (in posix the thread function have the signature void* (thread_func)(void*), something equal under windows too) - and you are completely free to send the pointer to your own data (struct or something) and use this from the thread function (casting pointer to proper type). well, memory management should be though out (so you neither leak memory nor use already freed memory from the thread), but this is a different issue

Java-ME Application in Freeze Mode

I am developing a Java-ME Based Mobile Application. Now My Requirements are like whenever I am updating one of my RMS, I want my application to be stay in a Freeze kind of mode; which means no other action like clicking button or anything else should happen. My Method is already "Synchronized".
Kindly guide me regarding this question.
Thanks.
The best way to handle this is to "serialize" your tasks. You can do this with a message queue - a class that maintains a Vector of message objects (tasks) and runs code based on each message. The queue runs on a thread that processes each task (message) in series. You create a simple message class for the different tasks - read RMS etc. A message can be an Integer if you like that wraps a number. The operation of adding and retrieving messages is synchronized but the code than does the tasks is not and runs on a simple switch block. The benefit of serializing your tasks is you don't have to worry about concurrency. Here is some of the essential code from a class I use to do this.
class MessageQueue implements Runnable{
Vector messages;
Thread myThread;
volatile boolean stop;
public void start() {
stop=false;
myThread=new Thread(this);
myThread.start();
}
// add message to queue - this is public
public synchronized void addMessage(Message m) {
messages.addElement(m);
if(stop) {
start();
} else {
// wake the thread
notify();
}
}
// get next message from queue - used by this thread
private synchronized Message nextMessage() {
if(stop) return null;
if(messages.isEmpty()) {
return null;
} else {
Message m=(Message)messages.firstElement();
messages.removeElementAt(0);
return m;
}
}
public void run() {
while (!stop) {
// make thread wait for messages
if (messages.size() == 0) {
synchronized (this) {
try {
wait();
} catch (Exception e) {
}
}
}
if (stop) {
// catch a call to quit
return;
}
processMessage();
}
}
}
// all the tasks are in here
private void processMessage() {
Message m = nextMessage();
switch (m.getType()) {
case Message.TASK1:
// do stuff
break;
case Message.TASK2:
// do other stuff
break;
case Message.TASK3:
// do other other stuff
break;
default: //handle bad message
}
}
}
What you are asking is very code depended. Usually when you want to make some synchronic actions you just write them one after the other. in java it's more complected, since sometimes you "ask" the system to do something (like repaint() method). But since the RMS read/write operations are very quick (few millisecond) i don't see any need in freesing.
Could you please provide some more information about the need (time for RMS to respond)? does your code runs on system thread (main thread) or your own thread?
I want my application to be stay in a Freeze kind of mode; which means no other action like clicking button or anything else should happen.
First of all I would strongly advise against real freezing of UI - this could make a suicidal user experience for your application.
If you ever happened to sit in front of computer frozen because of some programming bug, you may understand why approach like this is strongly discouraged. As they describe it in MIDP threading tutorial, "user interface freezes, the device appears to be dead, and the user becomes frustrated..."
This tutorial by the way also suggests possibly the simplest solution for problems like you describe: displaying a wait screen. If you don't really have reasons to avoid this solution, just do as tutorial suggests.
To be on a safe side, consider serializing tasks as suggested in another answer. This will ensure that when RMS update starts, there are no other tasks pending.

Resources