asincrono vs non bloccante


373

Qual è la differenza tra chiamate asincrone e non bloccanti? Anche tra blocco e chiamate sincrone (con esempi per favore)?



1
Ho capito bene le differenze leggendo il libro <Unix Networking Programming> Col ​​1, Capitolo 6.
Bin

2
Un articolo interessante: aumentare le prestazioni dell'applicazione usando l'I / O asincrono . Classifica i paradigmi I / O in 4 categorie: (1) Blocco + Sincrono, (2) Non blocco + Sincrono, (3) Blocco + Asincrono e (4) Non blocco + Asincrono.
MS Dousti,

@MSDousti Mi è stato detto che questo è sbagliato in qualche modo, da un esperto di Google.
Rick,

@MSDousti Dopo alcuni studi, penso che non ci siano combinazioni (3) e (2) come descritto nei commenti. Controlla la definizione di Asincrono, sta parlando della stessa cosa di Non-Blocking. Come puoi vedere la risposta migliore, sta confermando la mia opinione. Le funzioni di polling e callback sono semplicemente modi / schemi per implementare Asincrono. Sì, sto dicendo che Blocking, Synchronous e Non-Blocking, Asynchronous sono 2 coppie di sinonimi.
Rick,

Risposte:


305

In molte circostanze sono nomi diversi per la stessa cosa, ma in alcuni contesti sono abbastanza diversi. Quindi dipende. La terminologia non viene applicata in modo totalmente coerente in tutto il settore del software.

Ad esempio, nella classica API socket, un socket non bloccante è un socket che ritorna immediatamente immediatamente con uno speciale messaggio di errore "bloccherebbe", mentre un socket bloccante avrebbe bloccato. Devi usare una funzione separata come selecto pollper scoprire quando è il momento giusto per riprovare.

Ma i socket asincroni (come supportati dai socket di Windows) o il modello IO asincrono utilizzato in .NET sono più convenienti. Si chiama un metodo per avviare un'operazione e il framework ti richiama al termine. Anche qui, ci sono differenze fondamentali. I socket asincroni Win32 "eseguono il marshalling dei risultati su uno specifico thread della GUI passando messaggi di Windows, mentre IO asincrono .NET è a thread libero (non sai su quale thread verrà chiamato il callback).

Quindi non significano sempre la stessa cosa. Per distillare l'esempio del socket, potremmo dire:

  • Il blocco e il sincrono significano la stessa cosa: chiami l'API, riaggancia il thread fino a quando non ha qualche tipo di risposta e te lo restituisce.
  • Non bloccando significa che se una risposta non può essere restituita rapidamente, l'API ritorna immediatamente con un errore e non fa nient'altro. Quindi ci deve essere un modo correlato per interrogare se l'API è pronta per essere chiamata (ovvero, per simulare un'attesa in modo efficiente, per evitare il polling manuale in un circuito ristretto).
  • Asincrono significa che l'API ritorna sempre immediatamente, dopo aver avviato uno sforzo "in background" per soddisfare la tua richiesta, quindi ci deve essere un modo correlato per ottenere il risultato.

stato IO pronto anziché stato IO di completamento; su Linux vedi libaio
Will

4
Grazie per aver sottolineato che i termini sono sensibili al contesto e talvolta possono essere utilizzati in modo incoerente. Trovo soprattutto nella tecnologia, ma anche in altri settori, che spesso è più utile riconoscere questo fatto che entrare nei dibattiti su quale definizione precisa sia corretta, come talvolta accade.
Chad NB,

2
Seguito D: La risposta sembra fare due distinzioni diverse tra i termini. Innanzitutto, la notifica: il non-blocco implica che l'applicazione deve ricontrollare più tardi (polling) mentre l'async implica che possiamo dimenticarcene e fare affidamento sul framework / sistema operativo per avvisarci tramite callback o pubblicare un evento. In secondo luogo, l'azione: il non-blocco non fa assolutamente altro che restituire un errore, mentre asincrono mette in coda l'azione o lo fa "in background" in un certo senso. Quale differenza è più importante nel distinguere i termini? O la distinzione è più fortemente associata a un termine? O è ambiguo?
Chad NB,

2
@ChadNB - come termini, il non-blocco è fortemente associato al polling. Per quanto riguarda la questione se l'API "ricorda" il tuo tentativo di chiamarlo: l'unico motivo per cui l'API da ricordare è per richiamarti. Se lo chiamerai per eseguire nuovamente il polling, devi già mantenere lo stato necessario per sapere per effettuare quella chiamata successiva, quindi l'API non aggiungerebbe alcun valore mantenendo anche lo stato.
Daniel Earwicker,

6
Invece di dire che la chiamata non bloccante restituisce un "errore", penso che sarebbe più preciso affermare che una chiamata non bloccante fa tutto ciò che può essere fatto essenzialmente immediatamente, e quindi indica quanto ha fatto. Per alcune operazioni, la quantità di lavoro svolto sarà "tutto" o "niente", ma alcune altre operazioni (come l'I / O di flusso) potrebbero restituire un'indicazione quantitativa. Il non-blocco equivale semanticamente al blocco con un timeout molto breve se l'implementazione dell'I / O di blocco consentirà di ripetere senza problemi un'operazione di timeout (alcuni lo fanno; altri no).
Supercat,

56

sincrono / asincrono è descrivere la relazione tra due moduli.
blocco / non blocco è descrivere la situazione di un modulo.

Un esempio:
Modulo X: "I".
Modulo Y: "libreria".
X chiede Y: hai un libro chiamato "c ++ primer"?

1) blocco: prima che Y risponda X, X continua ad aspettare lì per la risposta. Ora X (un modulo) sta bloccando. X e Y sono due thread o due processi o un thread o un processo? non lo sappiamo.

2) non bloccante: prima che Y risponda X, X lascia semplicemente lì e fa altre cose. X può tornare ogni due minuti per verificare se Y ha terminato il suo lavoro? O X non tornerà finché Y non lo chiamerà? Non lo sappiamo. Sappiamo solo che X può fare altre cose prima che Y finisca il suo lavoro. Qui X (un modulo) non è bloccante. X e Y sono due thread o due processi o un processo? non lo sappiamo. MA siamo sicuri che X e Y non possano essere un thread.

3) sincrono: prima che Y risponda X, X continua ad aspettare lì per la risposta. Significa che X non può continuare fino a quando Y non termina il suo lavoro. Ora diciamo: X e Y (due moduli) sono sincroni. X e Y sono due thread o due processi o un thread o un processo? non lo sappiamo.

4) asincrono: prima che Y risponda X, X lascia lì e X può fare altri lavori. X non tornerà finché Y non lo chiamerà. Ora diciamo: X e Y (due moduli) sono asincroni. X e Y sono due thread o due processi o un processo? non lo sappiamo. MA siamo sicuri che X e Y non possano essere un thread.


Si prega di prestare attenzione alle due frasi in grassetto sopra. Perché la frase in grassetto nel 2) contiene due casi mentre la frase in grassetto nel 4) contiene solo un caso? Questa è una chiave della differenza tra non bloccante e asincrona.

Ecco un tipico esempio di non blocco e sincrono:

// thread X
while (true)
{
    msg = recv(Y, NON_BLOCKING_FLAG);
    if (msg is not empty)
    {
        break;
    }
    sleep(2000); // 2 sec
}

// thread Y
// prepare the book for X
send(X, book);

Puoi vedere che questo design non è bloccante (puoi dire che la maggior parte delle volte questo loop fa qualcosa di insensato ma agli occhi della CPU, X è in esecuzione, il che significa che X è non bloccante) mentre X e Y sono sincroni perché X può continuerai a fare qualsiasi altra cosa (X non può saltare fuori dal ciclo) fino a quando non ottiene il libro da Y.
Normalmente in questo caso, rendere il blocco X è molto meglio perché il non-blocco spende molte risorse per un ciclo stupido. Ma questo esempio è utile per aiutarti a capire il fatto: non bloccare non significa asincrono.

Le quattro parole ci rendono facilmente confusi, ciò che dovremmo ricordare è che le quattro parole servono per la progettazione dell'architettura. Imparare a progettare una buona architettura è l'unico modo per distinguerli.

Ad esempio, possiamo progettare un tale tipo di architettura:

// Module X = Module X1 + Module X2
// Module X1
while (true)
{
    msg = recv(many_other_modules, NON_BLOCKING_FLAG);
    if (msg is not null)
    {
        if (msg == "done")
        {
            break;
        }
        // create a thread to process msg
    }
    sleep(2000); // 2 sec
}
// Module X2
broadcast("I got the book from Y");


// Module Y
// prepare the book for X
send(X, book);

Nell'esempio qui, possiamo dirlo

  • X1 non è bloccante
  • X1 e X2 sono sincroni
  • X e Y sono asincroni

Se necessario, puoi anche descrivere quei thread creati in X1 con le quattro parole.

Le cose più importanti sono: quando utilizziamo sincrono anziché asincrono? quando utilizziamo il blocco anziché il non blocco?

Perché Nginx non è bloccante? Perché il blocco di Apache?

Per fare una buona scelta, devi analizzare le tue necessità e testare le prestazioni di diverse architetture. Non esiste un'architettura simile adatta a varie esigenze.


7
IMO la migliore risposta poiché coglie l'essenza del concetto: la relazione tra uno o due partecipanti.
Fábio,

in 1 e 3, Y agisce come una risorsa LIMITATA. Non ci sono più Y per aiutare X
UVM il

46
  • Asincrono si riferisce a qualcosa fatto in parallelo , diciamo che è un altro thread.
  • Il non blocco si riferisce spesso al polling , vale a dire verificare se una determinata condizione è valida (il socket è leggibile, il dispositivo ha più dati, ecc.)

17
quando è coinvolto l'I / O, in genere asincrono non è "in parallelo", né "un altro thread", principalmente basato su notifiche. cioè: non bloccare, non eseguire il polling, basta ottenere il segnale. certo, si può sostenere che il segnale proviene dal "mondo reale", che può essere pensato come "un altro thread" ...
Javier,

Bene, sì, possiamo discutere la formulazione esatta tutto il giorno :)
Nikolai Fetissov

ma come si spiega l'AIO in Linux? che utilizzava sia Async che non bloccanti. LINK AIO
Djvu,

16
A chiunque legga questa risposta: non si discute sulla formulazione esatta. Allo stesso modo che la concorrenza e il parallelismo non sono le stesse nozioni e distinguerle non è un problema di formulazione. Asincronicità e parallelismo sono due bestie diverse e questa risposta in modo impreciso le rende uguali.
Ptival

2
Async non significa necessariamente che sia fatto in parallelo, vedi questo fantastico post su StackOverflow sulla programmazione simultanea e parallela.
BARJ,

17

Mettendo questa domanda nel contesto di NIO e NIO.2 in java 7, l'IO asincrono è un passo più avanzato rispetto al non blocco. Con le chiamate non bloccanti NIO Java, si impostano tutti i canali (SocketChannel, ServerSocketChannel, FileChannel, ecc.) Come tali chiamando AbstractSelectableChannel.configureBlocking(false). Dopo il ritorno di quelle chiamate IO, tuttavia, sarà probabilmente necessario controllare i controlli come se e quando rileggere / scrivere, ecc.
Ad esempio,

while (!isDataEnough()) {
    socketchannel.read(inputBuffer);
    // do something else and then read again
}

Con l'API asincrono di Java 7, questi controlli possono essere realizzati in modi più versatili. Uno dei 2 modi è usare CompletionHandler. Si noti che entrambe le readchiamate non sono bloccanti.

asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */, 
    new CompletionHandler<Integer, Object>() {
        public void completed(Integer result, Object attachment) {...}  
        public void failed(Throwable e, Object attachment) {...}
    }
}

3
FileChannelnon è selezionabile e non può essere configurato per non bloccare.
Michaelliu,

15

Come probabilmente puoi vedere dalla moltitudine di risposte diverse (e spesso reciprocamente esclusive), dipende da chi chiedi. In alcune arene, i termini sono sinonimi. Oppure potrebbero riferirsi a due concetti simili:

  • Un'interpretazione è che la chiamata farà qualcosa in background essenzialmente senza supervisione al fine di consentire al programma di non essere trattenuto da un lungo processo che non è necessario controllare. La riproduzione dell'audio potrebbe essere un esempio: un programma potrebbe chiamare una funzione per riprodurre (diciamo) un mp3, e da quel momento in poi potrebbe continuare su altre cose lasciandolo al sistema operativo per gestire il processo di rendering dell'audio sull'hardware audio .
  • L'interpretazione alternativa è che la chiamata farà qualcosa che il programma dovrà monitorare, ma consentirà che la maggior parte del processo si verifichi in background solo notificando il programma in punti critici del processo. Ad esempio, il file asincrono IO può essere un esempio: il programma fornisce un buffer al sistema operativo per scrivere su file e il sistema operativo avvisa il programma solo quando l'operazione è completa o si verifica un errore.

In entrambi i casi, l'intenzione è quella di non bloccare il programma in attesa del completamento di un processo lento: l'unica vera differenza è la risposta del programma. Quale termine si riferisce a quale cambia anche da programmatore a programmatore, da lingua a lingua o da piattaforma a piattaforma. Oppure i termini possono riferirsi a concetti completamente diversi (come l'uso di sincrono / asincrono in relazione alla programmazione di thread).

Ci dispiace, ma non credo che ci sia una sola risposta giusta che sia globalmente vera.


1
+1 buona risposta. Le persone devono essere consapevoli del fatto che "asincrono" può significare l' approccio non-bloccante o Microsoft asynch (basato sugli eventi / callback).
Ingegnere,

14

Una chiamata non bloccante ritorna immediatamente con tutti i dati disponibili: il numero completo di byte richiesti, meno o nessuno.

Una chiamata asincrona richiede un trasferimento che verrà eseguito nella sua interezza (totalità) ma verrà completato in futuro.


il non blocco non restituisce alcun risultato nulla
CEO di Apartico

9

Non bloccante: questa funzione non attende mentre si trova nello stack.

Asincrono: il lavoro può continuare per conto della chiamata di funzione dopo che quella chiamata ha lasciato lo stack


1
@Marenz significa che non è possibile eseguire direttamente io non bloccante con le chiamate posix. Ciò non cambia il significato che dà qui.
tmc

@Marenz Il che significa solo che il flag viene ignorato per i file. Non influisce sul significato di questa risposta.
Marchese di Lorne,

8

Sincrono è definito come accadendo contemporaneamente.

L'asincrono viene definito come non accada contemporaneamente.

Questo è ciò che provoca la prima confusione. Sincrono è in realtà ciò che è noto come parallelo. Mentre asincrono è sequenziale, farlo, quindi farlo.

Ora l'intero problema riguarda la modellazione di un comportamento asincrono, perché hai alcune operazioni che richiedono la risposta di un'altra prima che possa iniziare. Quindi è un problema di coordinamento, come farai a sapere che ora puoi iniziare quell'operazione?

La soluzione più semplice è nota come blocco.

Il blocco si verifica quando si sceglie semplicemente di attendere che venga eseguita l'altra cosa e si restituisca una risposta prima di passare all'operazione che ne aveva bisogno.

Quindi, se hai bisogno di mettere il burro su pane tostato, e quindi devi prima tostare l'allevamento. Il modo in cui li coordineresti è che prima brindavi all'allevamento, poi fissavi all'infinito il tostapane fino a quando non fa scoppiare il toast, e poi procedi a metterli sopra il burro.

È la soluzione più semplice e funziona molto bene. Non c'è alcun motivo reale per non usarlo, a meno che tu non abbia anche altre cose che devi fare che non richiedono il coordinamento con le operazioni. Ad esempio, facendo alcuni piatti. Perché aspettare fissando costantemente il tostapane per far scoppiare il toast, quando sai che ci vorrà un po 'di tempo e potresti lavare un intero piatto mentre finisce?

È qui che entrano in gioco altre due soluzioni note rispettivamente come non bloccanti e asincrone.

Il blocco non è quando si sceglie di fare altre cose non correlate mentre si attende che l'operazione venga eseguita. Verifica la disponibilità della risposta come ritieni opportuno.

Quindi, invece di guardare il tostapane per farlo scoppiare. Vai a lavare un piatto intero. E poi dai un'occhiata al tostapane per vedere se sono spuntati i toast. Se non l'hanno fatto, vai a lavare un altro piatto, controllando il tostapane tra ogni piatto. Quando vedi che i toast sono scoppiati, smetti di lavare i piatti e invece prendi il toast e vai a metterli sopra il burro.

Dover controllare costantemente i toast può essere fastidioso, immagina che il tostapane sia in un'altra stanza. Tra un piatto e l'altro perdi il tuo tempo andando in quell'altra stanza per controllare il toast.

Ecco che arriva asincrono.

Asincrono è quando si sceglie di fare altre cose non correlate mentre si attende che l'operazione venga eseguita. Invece di controllarlo, però, deleghi il lavoro di verifica a qualcos'altro, potrebbe essere l'operazione stessa o un osservatore, e hai quella cosa avvisare e possibilmente interrompere te quando la risposta è disponibile in modo da poter procedere con l'altra operazione che ne avevo bisogno.

È una strana terminologia. Non ha molto senso, dal momento che tutte queste soluzioni sono modi per creare un coordinamento asincrono di attività dipendenti. Ecco perché preferisco chiamarlo evented.

Quindi, per questo, decidi di aggiornare il tuo tostapane in modo che emetta un segnale acustico al termine dei toast. Ti capita di ascoltare costantemente, anche mentre fai i piatti. Ascoltando il segnale acustico, ti metti in coda in memoria che non appena avrai finito di lavare il tuo attuale piatto, ti fermerai e andrai a mettere il burro sul toast. Oppure potresti scegliere di interrompere il lavaggio del piatto attuale e occuparti subito del brindisi.

Se hai problemi ad ascoltare il segnale acustico, puoi chiedere al tuo partner di guardare il tostapane e venire a dirti quando il brindisi è pronto. Il tuo partner può scegliere una delle tre strategie precedenti per coordinare il suo compito di guardare il tostapane e dirti quando sono pronti.

In ultima analisi, è bene capire che mentre non-blocking e async (o quello che preferisco chiamare evented) ti permettono di fare altre cose mentre aspetti, non ce l'hai anche. Puoi scegliere di eseguire un ciclo continuo per controllare lo stato di una chiamata non bloccante, senza fare altro. Tuttavia, spesso è peggio del blocco (come guardare il tostapane, quindi allontanarlo, quindi riprovare fino al suo completamento), quindi molte API non bloccanti ti consentono di passare a una modalità di blocco da esso. Per quanto riguarda gli eventi, puoi semplicemente attendere inattivo fino a quando non ricevi una notifica. L'aspetto negativo in quel caso è che l'aggiunta della notifica è stata complessa e potenzialmente costosa all'inizio. Dovevi comprare un nuovo tostapane con la funzione bip o convincere il tuo partner a guardarlo per te.

E un'altra cosa, è necessario rendersi conto dei compromessi forniti da tutti e tre. Uno non è ovviamente migliore degli altri. Pensa al mio esempio. Se il tuo tostapane è così veloce, non avrai il tempo di lavare un piatto, nemmeno iniziare a lavarlo, ecco quanto è veloce il tuo tostapane. Iniziare a fare qualcos'altro in quel caso è solo una perdita di tempo e fatica. Il blocco lo farà. Allo stesso modo, se lavare un piatto impiegherà 10 volte di più della tostatura. Devi chiederti cosa c'è di più importante da fare? Il brindisi potrebbe diventare freddo e duro a quel punto, non ne vale la pena, anche il blocco farà. Oppure dovresti scegliere cose più veloci da fare mentre aspetti. C'è di più ovviamente, ma la mia risposta è già piuttosto lunga, il mio punto è che devi pensare a tutto ciò e alle complessità dell'implementazione di ciascuno per decidere se ne valga la pena e se '

Modificare:

Anche se questo è già lungo, voglio anche che sia completo, quindi aggiungerò altri due punti.

1) Esiste anche comunemente un quarto modello noto come multiplexato . Questo è quando mentre aspetti un'attività, ne avvii un'altra e mentre aspetti entrambe, ne avvii un'altra e così via, fino a quando non hai molte attività tutte avviate e poi, aspetti inattivo, ma su tutto loro. Quindi appena hai finito, puoi procedere con la gestione della sua risposta e poi tornare ad aspettare gli altri. È noto come multiplex, perché mentre aspetti, devi controllare ogni attività una dopo l'altra per vedere se sono state completate, ad vitam, fino a quando non lo sei. È un po 'un'estensione oltre al normale non bloccante.

Nel nostro esempio sarebbe come avviare il tostapane, quindi la lavastoviglie, quindi il forno a microonde, ecc. E poi aspettare su uno di essi. Dove controlleresti il ​​tostapane per vedere se è fatto, in caso contrario, controlleresti la lavastoviglie, in caso contrario, il microonde e ancora.

2) Anche se credo che sia un grosso errore, sincrono è spesso usato per significare una cosa alla volta. E asincrone molte cose alla volta. In questo modo vedrai il blocco sincrono e il non blocco usati per riferirsi al blocco e al non blocco. E il blocco asincrono e il non-blocco utilizzati per riferirsi a multiplexing ed evented.

Non capisco davvero come ci siamo arrivati. Ma quando si tratta di IO e calcolo, sincrono e asincrono si riferiscono spesso a ciò che è meglio noto come non sovrapposto e sovrapposto. Cioè, asincrono significa che IO e calcolo sono sovrapposti, ovvero che avvengono contemporaneamente. Mentre sincrono significa che non lo sono, quindi accadendo in sequenza. Per il non blocco sincrono, ciò significherebbe che non si avvia un altro IO o calcolo, si deve solo aspettare e simulare una chiamata di blocco. Vorrei che le persone smettessero di abusare sincrono e asincrono in quel modo. Quindi non lo sto incoraggiando.


Non sei sicuro del motivo per cui hai detto "Sincrono è definito come accadendo contemporaneamente"? L'idea è che non è simultanea, ovvero non accade allo stesso tempo.
Helsing,

È stata una grande analogia! L'hai appena tostato!
d-coder,

@Helsing Questo è letteralmente il significato della parola. Sincrono significa stesso orario e asincrono non significa stesso tempo: p. Il motivo per cui qualcosa è asincrono, è perché non può accadere allo stesso tempo, deve accadere prima o dopo. Se potesse accadere allo stesso tempo, potresti semplicemente parallelizzarlo o farlo in qualsiasi ordine e non avresti bisogno di una sincronizzazione esplicita. Ecco perché la programmazione asincrona consiste nel fare questo, poi quello, attendere queste cose e poi, ecc. Perché nessuna di queste cose può accadere insieme allo stesso tempo.
Didier A.

@Helsing Inoltre, la simultanea non è la stessa del parallelo. Ciò non significa che due cose stiano accadendo allo stesso tempo, significa solo progressi su più di una cosa prima che una di esse finisca. Ciò potrebbe essere realizzato con la parallelizzazione, o semplicemente con l'interleaving, ovvero il cambio di attività.
Didier A.

5

Blocco della chiamata: il controllo ritorna solo al termine della chiamata.

Chiamata senza blocco : il controllo ritorna immediatamente. Il sistema operativo successivo in qualche modo notifica al processo che la chiamata è completa.


Programma sincrono : un programma che utilizza il blocco delle chiamate. Per non bloccarsi durante la chiamata, deve contenere 2 o più thread (ecco perché si chiama Synchronous: i thread vengono eseguiti in modo sincrono).

Programma asincrono : un programma che utilizza chiamate senza blocco . Può avere solo 1 thread e rimane comunque interattivo.


1
Chiamata senza blocco: il controllo ritorna dopo aver fatto tutto ciò che può essere fatto essenzialmente immediatamente; il metodo indica quanto è stato fatto. È diverso da una chiamata asincrona, che si comporta come descritto per il blocco della chiamata.
supercat

0

Differiscono solo per l'ortografia. Non vi è alcuna differenza in ciò a cui si riferiscono. Per essere tecnici potresti dire che differiscono per enfasi. Il non blocco si riferisce al flusso di controllo (non blocca.) Asincrono si riferisce a quando l'evento \ dati viene gestito (non in modo sincrono).


0

I modelli di blocco richiedono che l'applicazione di avvio si blocchi all'avvio dell'I / O. Ciò significa che non è possibile sovrapporre elaborazione e I / O contemporaneamente. Il modello sincrono non bloccante consente la sovrapposizione di elaborazione e I / O, ma richiede che l'applicazione controlli lo stato dell'I / O su base ricorrente. Ciò lascia un I / O asincrono non bloccante, che consente la sovrapposizione di elaborazione e I / O, inclusa la notifica del completamento dell'I / O.


-2

Blocco: il controllo ritorna al richiamo della precessione al termine dell'elaborazione della primitiva (sincronizzazione o asincronizzazione)

Non bloccante: il controllo ritorna al processo immediatamente dopo l'invocazione


10
Questo non risponde nemmeno a ciò che viene chiesto.
Koray Tugay,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.