Use blocking sockets from non-main threads in wxProtocol.
Non-blocking sockets can't work in worker threads without additional locking as they generate events that can be dispatched from the main thread after the socket object, created in the worker thread, is already destroyed, so don't even attempt to use them if wxProtocol object is created from non-main thread. Also simplify the code by removing the calls to SetFlags(), Notify() and {Save,Restore}State() and simply put the socket from the beginning in blocking, wait all mode that it needs to be in. This, with the fixes in the previous commit, allows wxHTTP and wxFTP to work from worker threads too. Test using wxHTTP from a worker thread in the socket client sample. Closes #17031.
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "wx/socket.h"
|
||||
#include "wx/url.h"
|
||||
#include "wx/sstream.h"
|
||||
#include "wx/thread.h"
|
||||
#include <memory>
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -575,23 +576,13 @@ void MyFrame::OnDatagram(wxCommandEvent& WXUNUSED(event))
|
||||
|
||||
#if wxUSE_URL
|
||||
|
||||
void MyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))
|
||||
void DoDownload(const wxString& urlname)
|
||||
{
|
||||
// Ask for the URL
|
||||
static wxString s_urlname("http://www.google.com/");
|
||||
wxString urlname = wxGetTextFromUser
|
||||
(
|
||||
_("Enter an URL to get"),
|
||||
_("URL:"),
|
||||
s_urlname
|
||||
);
|
||||
if ( urlname.empty() )
|
||||
return; // cancelled by user
|
||||
wxString testname("URL");
|
||||
if ( !wxIsMainThread() )
|
||||
testname += " in worker thread";
|
||||
|
||||
s_urlname = urlname;
|
||||
|
||||
|
||||
TestLogger logtest("URL");
|
||||
TestLogger logtest(testname);
|
||||
|
||||
// Parse the URL
|
||||
wxURL url(urlname);
|
||||
@@ -626,6 +617,51 @@ void MyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))
|
||||
urlname, sout.GetString());
|
||||
}
|
||||
|
||||
void MyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
// Ask for the URL
|
||||
static wxString s_urlname("http://www.google.com/");
|
||||
wxString urlname = wxGetTextFromUser
|
||||
(
|
||||
_("Enter an URL to get"),
|
||||
_("URL:"),
|
||||
s_urlname
|
||||
);
|
||||
if ( urlname.empty() )
|
||||
return; // cancelled by user
|
||||
|
||||
s_urlname = urlname;
|
||||
|
||||
// First do it in this thread.
|
||||
DoDownload(urlname);
|
||||
|
||||
// And then also in a worker thread.
|
||||
#if wxUSE_THREADS
|
||||
class DownloadThread : public wxThread
|
||||
{
|
||||
public:
|
||||
explicit DownloadThread(const wxString& url): m_url(url)
|
||||
{
|
||||
Run();
|
||||
}
|
||||
|
||||
virtual void* Entry() wxOVERRIDE
|
||||
{
|
||||
DoDownload(m_url);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
const wxString m_url;
|
||||
};
|
||||
|
||||
// NB: there is a race condition here, we don't check for this thread
|
||||
// termination before exiting the application, don't do this in real code!
|
||||
new DownloadThread(urlname);
|
||||
#endif // wxUSE_THREADS
|
||||
}
|
||||
|
||||
#endif // wxUSE_URL
|
||||
|
||||
void MyFrame::OnSocketEvent(wxSocketEvent& event)
|
||||
|
Reference in New Issue
Block a user