Per quanto comprendo e conosco il metodo della TThread Class, se sincronizzi il tuo codice, in realtà viene eseguito nel thread principale dell'applicazione (proprio come un timer/tasto clic/ecc.) Ho giocato in giro e notato che un MessageBox NON blocca l'applicazione principale, tuttavia il sonno fa come previsto. Perché?Perché un MessageBox non blocca l'applicazione su un thread sincronizzato?
risposta
Ci sono due parti per questa risposta.
La parte 1 è spiegata correttamente in If MessageBox()/related are synchronous, why doesn't my message loop freeze?. La funzione MessageBox non sta bloccando, ma crea semplicemente una finestra di dialogo con il proprio loop di messaggi.
La parte 2 è spiegata nello MessageBox documentation.
hWnd: un handle alla finestra del proprietario della finestra di messaggio da creare. Se il parametro è NULL, la finestra del messaggio non ha una finestra del proprietario.
Quando si visualizza una finestra di dialogo modale, Windows disabilita il suo proprietario, ma se si passa 0 per il primo parametro, non c'è nulla di proprietario e disattivare. Pertanto, il tuo programma continuerà ad elaborare i messaggi (e reagire ad essi) mentre viene visualizzata la finestra di messaggio.
Per modificare questo comportamento, passare l'handle del modulo come primo parametro. Per esempio:
procedure TTestThread.SynchThread;
begin
MessageBoxA (Form1.Handle, 'Hello', 'Test', 0);
end;
La tua parte 2 non è precisa. Non avere proprietario non cambia il ciclo dei messaggi che rimuove i messaggi. MessageBox è ancora sincrono e fino a quando non ritorna, il suo ciclo di messaggi estrae i messaggi in coda. Quando si passa una finestra del proprietario ad una finestra di dialogo modale, la finestra di dialogo modale disabilita il proprietario, il suo proprietario e così via. –
David, grazie. Corretto. – gabr
Synchronize eseguirà il codice nel Mainthread.
Una buona spiegazione può essere trovata qui Synchronization in Delphi TThread class
Devi solo impedire all'utente di interagire con i moduli della tua applicazione, ad es. da
procedure TTestThread.SynchThread;
begin
MessageBoxA (0, 'Hello', 'Test', MB_TASKMODAL);
end;
utilizzando MessageBoxA come hai fatto tu, non impedirà il Mainthread di reagire a questi eventi triggerd da ueser interazione con i moduli, basta provare
procedure TForm4.Button2Click(Sender: TObject);
begin
MessageBoxA (0, 'Hello', 'Test', 0);
// vs
// MessageBoxA (0, 'Hello', 'Test', MB_TASKMODAL);
end;
che la sincronizzazione sarà può essere eseguito nel thread principale può essere mostrato (IMHO) da
type
TTestThread = class(TThread)
private
FSync:Boolean;
FCalled:TDateTime;
procedure SynchThread;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean;sync:Boolean);
end;
procedure TTestThread.SynchThread;
begin
MessageBox (0,PChar(DateTimeToStr(FCalled)+#13#10+DateTimeToStr(Now)),'Hello' , 0);
end;
procedure TTestThread.Execute;
begin
sleep(100); // give Caller Time to fell asleep
if Fsync then Synchronize (SynchThread) else SynchThread;
end;
constructor TTestThread.Create(CreateSuspended: Boolean;sync:Boolean);
begin
inherited Create(CreateSuspended);
FSync := Sync;
FCalled :=Now;
FreeOnTerminate := True;
end;
procedure StartThread(sync:Boolean);
var
TestThread : TTestThread;
begin
TestThread := TTestThread.Create (FALSE,sync);
end;
procedure TForm4.RunUnsynchronizedClick(Sender: TObject);
begin
StartThread(false);// no sync
Sleep(5000); // Stop messageloop
end;
procedure TForm4.RunSynchronizedClick(Sender: TObject);
begin
StartThread(true); // sync
Sleep(5000); // Stop messageloop
end;
Allora, perché è questo essere downvoted, mi sembra che il parametro MB_TASKMODAL è un buon suggerimento. @bummi perché non passare la maniglia della finestra di mainform? – Remko
@Remko prima della mia prima modifica ho avuto anche una chiamata con application.handle. Il downvote sarà causato da diversi punti di vista sul "blocco". – bummi
Chiunque là fuori sa come funziona 'MB_TASKMODAL'? Disabilita tutte le finestre di primo livello di proprietà del processo di chiamata? –
Ho il sospetto che la questione si riduce a ciò che si intende quando si dice:
scatola Un messaggio non blocca l'applicazione principale.
Quello che prendo questo significa che quando si visualizza la finestra di messaggio, il modulo VCL può ancora essere interagito con. Il problema qui non è correlato ai thread e suggerisco di rimuoverli dall'equazione. La tua comprensione di cosa fa Synchronize
è valida.
Il problema è interamente correlato al concetto di window's owner e al comportamento delle finestre di dialogo modali rispetto ai rispettivi proprietari.Si noti che dal proprietario, non intendo la proprietà Delphi TComponent.Owner
, ma intendo il significato dell'API di Windows di owner.
Creare un'app VCL e rilasciare due pulsanti sul modulo. Aggiungi i seguenti gestori OnClick
.
procedure TForm1.Button1Click(Sender: TObject);
begin
MessageBox(0, 'Not owned', nil, MB_OK);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MessageBox(Handle, 'Owned by the VCL form', nil, MB_OK);
end;
Ora osservare ciò che accade quando si fa clic su Button1
. Viene visualizzata la finestra di messaggio, ma è ancora possibile fare clic sul modulo VCL. E confrontare con Button2
. Quando mostra la finestra del messaggio, non è possibile interagire con il modulo VCL.
Quando viene visualizzata una finestra di dialogo modale, la finestra di dialogo ne disabilita il proprietario. Nel caso di Button2
, il proprietario è il modulo VCL. E una volta disabilitato il modulo, non puoi interagire con esso. Nel caso di Button1
, non esiste un proprietario e quindi la finestra di dialogo modale non disabilita altre finestre. Ecco perché è possibile interagire con il modulo VCL.
Raymond Chen ha una lunga serie sulle modalità al suo vecchio blog New Thing:
- Modality, part 1: UI-modality vs code-modality
- Modality, part 2: Code-modality vs UI-modality
- Modality, part 3: The WM_QUIT message
- Modality, part 4: The importance of setting the correct owner for modal UI
- Modality, part 5: Setting the correct owner for modal UI
- Modality, part 6: Interacting with a program that has gone modal
- Modality, part 7: A timed MessageBox, the cheap version
- Modality, part 8: A timed MessageBox, the better version
- Modality, part 9: Setting the correct owner for modal UI, practical exam
- 1. Perché lapplicazione non funziona su oggetti S4 che hanno un metodo as.list.default?
- 2. posso utilizzare sincronizzato su un campo finale?
- 3. Twisted: perché passare un callback posticipato a un thread posticipato blocca improvvisamente il thread?
- 4. Thread si blocca su WifiManager.enableNetwork()
- 5. Esecuzione di un nuovo thread all'interno di un blocco sincronizzato
- 6. Perché EclEmma non è sincronizzato (MyClass.class)?
- 7. MessageBox sul thread di lavoro
- 8. Come possono due thread essere "in" un metodo "sincronizzato"
- 9. MessageBox senza focus su un MessageBoxButton
- 10. Due thread possono accedere contemporaneamente a un metodo sincronizzato?
- 11. perché il metodo sincronizzato consente l'esecuzione contemporanea di più thread?
- 12. perché il metodo sincronizzato non funziona per il multithread
- 13. NSURLConnection blocca il thread principale?
- 14. Creazione di un MessageBox che non interrompe il codice?
- 15. Inserire un collegamento ipertestuale in un MessageBox
- 16. Quando è preferibile AtomicInteger su sincronizzato?
- 17. @sincronizzato in un metodo statico
- 18. Perché Collections.Generic.Queue non ha il metodo sincronizzato ma Collections.Queue ha?
- 19. Perché Console.ReadKey() blocca l'output di Console.WriteLine chiamato in un altro thread?
- 20. Thread starvation mentre si blocca un loop in Python
- 21. Come determinare se un oggetto è bloccato (sincronizzato) in modo da non bloccare in Java?
- 22. Perché il codice si blocca con HashMap.put() da più thread?
- 23. Java: cosa succede quando un nuovo thread viene avviato da un blocco sincronizzato?
- 24. AVPlayer non sincronizzato
- 25. Chiamare un metodo sincronizzato da un metodo sincronizzato, entrambi dello stesso oggetto
- 26. Come lasciare che un thread che blocca su recv() esca con garbo?
- 27. Qual è la differenza tra un metodo sincronizzato e un blocco sincronizzato in Java?
- 28. Thread.join blocca il thread principale
- 29. Passare un nuovo oggetto locale a un thread, thread-safe?
- 30. Perché PHP si blocca occasionalmente su session_start()
Spiegare cosa si intende per "bloccare l'applicazione principale" –