Domanda

Ho un servizio web ASP.NET che esegue operazioni pesanti, come ad esempio alcune operazioni sui file o la generazione di fogli Excel da una serie di report di cristallo. Non voglio essere bloccato chiamando questo servizio Web, quindi desidero rendere il servizio Web asincrono. Inoltre, desidero chiamare questo servizio Web da una pagina Web e voglio un meccanismo che mi consenta di continuare a eseguire il polling del server in modo che io possa mostrare alcuni indicatori di progresso sullo schermo, come dire il numero di file che sono stati elaborati. Si prega di notare che non desidero ricevere una notifica al completamento della chiamata del metodo Web, ma piuttosto uno stato di avanzamento in tempo reale. Come posso procedere?

È stato utile?

Soluzione

Scrivi un metodo separato sul server che puoi interrogare passando l'ID del lavoro che è stato programmato e che restituisce un valore approssimativo tra 0-100 (o 0,0 e 1,0, o qualunque altra) di quanto è lungo .

es. in stile REST, è possibile effettuare una richiesta GET su http://yourserver.com/app/jobstatus/4133/ che restituirebbe un semplice '52' come text / plain . Quindi devi solo interrogarlo ogni (secondo? Due secondi? Dieci secondi?) Per vedere quanto è lungo.

Il modo in cui realizzi effettivamente il monitoraggio sul back-end dipende enormemente dal tuo processo e da come funziona.

Altri suggerimenti

Penso che il servizio web XML sia lento, quindi la creazione di più metodi e polling i progressi saranno estremamente lenti e genereranno un carico enorme sul server. Non lo farei nell'ambiente di produzione. Vedo gli stessi (ma minori) problemi con il polling del database.

Prova invece Estensioni SOAP . Implementa un modello guidato dagli eventi. Vedere Aggiunta di una barra di avanzamento all'applicazione client del servizio Web su MSDN .

Puoi anche utilizzare SoapExtensions per avvisare il tuo cliente del download / avanzamento del processo. Il server può quindi inviare eventi al client. Nulla nel client deve essere modificato se non lo si utilizza.

Permette qualcosa del genere nel tuo client:

//...
private localhost.MyWebServiceService _myWebService = new localhost.MyWebServiceService ();
_myWebService.processDelegate += ProgressUpdate;
_myWebService.CallHeavyMethod();
//...

private void ProgressUpdate(object sender, ProgressEventArgs e)
{
  double progress = ((double)e.ProcessedSize / (double)e.TotalSize) * 100.00;
  //Show Progress...
}

Avere l'iniziale " inizia la generazione di rapporti " la chiamata al servizio Web crea un'attività in un pool di attività e restituisce al chiamante l'ID dell'attività.

Quindi, fornisci un altro metodo che restituisce la "percentuale eseguita". per un determinato taskId.

Fornire un terzo metodo che restituisce il risultato effettivo per un'attività completata.

Il modo più semplice sarebbe fare in modo che il servizio Web aggiorni un campo su un database con l'avanzamento della chiamata, quindi creare un servizio Web che interroghi quel campo e restituisca il valore.

Rendi il servizio Web in grado di restituire una sorta di ID attività o ID sessione. Crea un altro metodo web per eseguire query con quell'ID, che restituisce le informazioni necessarie (% completamento, elenco di file, qualunque cosa). Esegui il polling di questo metodo a intervalli regolari dal client.

Utilizzare un database per archiviare le informazioni sul processo, se lo si fa in memoria del servizio Web, ciò non si ridimensionerà bene nell'ambiente della Web farm, poiché potrebbe accadere che l'attività venga eseguita su un altro server, rispetto a quello che si è polling.

EDIT: ho appena visto un'altra risposta simile e commentarla. Il commentatore ha ragione: puoi usare la tabella in memoria per evitare le operazioni del disco, ma usando comunque un server db separato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top