19 messaggi dal 26 maggio 2006
Devo lanciare un metodo su un WebService. Il metodo deve effettuare dei calcoli e restituire al chiamante un risultato. Fin qui nulla di difficile, ma ho necessità che questo metodo prima di restituire avvii un thread che deve eseguire una serie di operazioni che possono richiedere anche alcuni minuti.

Ecco l'esempio di ciò che ho fatto

<WebMethod()> _
Public Function Metodo() As Boolean
'... Serie di calcoli

'Attivo il delegate
Dim x As New DPPDelegate(AddressOf DPPConvert)
x.Invoke()

Return True
End Function


Ho provato a lanciare un delegate e anche a utilizzare un backgroundprocess ma il callback del webservice rimane appeso fino a quando questo processo secondario non ha finito. Arriva ad eseguire l'istruzione 'Return True' mentre il DPPDelegate sta eseguendo le operazioni, ma il chiamante non riceve nulla di ritorno se non fino a quando il delegate non ha finito. Come posso fare?
501 messaggi dal 09 giugno 2006
Contributi
Ciao.

Il problema, più che altro, è capire dove vuoi "guadagnare tempo" (ossia dove vuoi beneficiare dell'uso del thread). Immagino che sia nell'applicazione client che richiama il WS. In tal caso il WS può chiamare il metodo DPPConvert in modo tradizionale mentre il client dovrebbe invocare il WebMethod usando la forma asincrona (BeginMetodo e EndMetodo se il client è sviluppato in .NET ed hai utilizzato la web reference).

Ciao.

.:. Marcello Rutter .:.
19 messaggi dal 26 maggio 2006
ho provato ma è uguale.
Se chiamo il webmethod in modalità asincrona la callback non mi viene restituita fino a quando il thread secondario all'interno del webmethod non ha finito l'elaborazione...
501 messaggi dal 09 giugno 2006
Contributi
Puoi postare qualche riga di codice del client con la chiamata asincrona? Quale versione di .NET utilizzi nel client?

.:. Marcello Rutter .:.
19 messaggi dal 26 maggio 2006
La versione che uso è la 2.0

Il codice del webmethod è quello già postato... a grandi linee

IL WEBSERVICE:
private Delegate Sub DPPDelegate()

<WebMethod()> _
Public Function AvviaConversione() As Boolean
dim bCanConvert as boolean

'... Serie di calcoli
bCanConverter = true

if bCanConverter Then
'Attivo il delegate
Dim x As New DPPDelegate(AddressOf DPPConvert)
x.Invoke()
End If

Return bCanConverter
End Function

Private Sub DPPConvert()
'... Sequenza di operazioni di conversione e di scrittura e copia di file
End Sub

IL CLIENT CON CHIAMATA SINCRONA:
- Il risultato della operazione non mi viene restituito fino a quando non ha finito l'esecuzione di DPPConverter benchè il return del webmethod sia stato eseguito
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
If WS.AvviaConversione() Then
messagebox.show("Conversione iniziata")
Else
messagebox.show("Conversione impossibile")
End If
End Sub

IL CLIENT CON CHIAMATA ASINCRONA:
- L'evento di fine esecuzione del webmethod non viene scatenato fino a quando non ha finito l'esecuzione di DPPConverter benchè il return del webmethod sia stato eseguito.
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
WS.AvviaConversioneAsync()
End Sub

Private Sub WS_AvviaConversioneCompleted(ByVal sender As Object, ByVal e As WS.AvviaConversioneCompletedEventArgs) Handles WS.AvviaConversioneCompleted
If e.Result Then
messagebox.show("Conversione iniziata")
Else
messagebox.show("Conversione impossibile")
End If
End Sub

Nel secondo caso non tengo impegnato il client in quanto la chiamata è asincrona ma non mi arriva la risposta del webmethod e non posso procedere con l'operatività del resto del software client fino a quando non mi arriva

Spero di essere stato chiaro nell'esposizione... grazie per la consulenza
501 messaggi dal 09 giugno 2006
Contributi
Ciao.

Partiamo dal secondo esempio. Mi sembra di capire che

WS.AvviaConversioneAsync() 


funzioni, nel senso che il metodo esce immediatamente senza attendere che il webmethod termini il proprio lavoro (mi confermi che è così?).

Ora, nel WebMethod dovresti chiamare "DPPConvert" senza thread o altro:

<WebMethod()> _ 
Public Function AvviaConversione() As Boolean 
dim bCanConvert as boolean 

'... Serie di calcoli 
bCanConverter = true 

if bCanConverter Then 
DPPConvert()
End If 

Return bCanConverter 
End Function


Al termine dell'esecuzione del WS nel server web dovrebbe arrivarti l'evento associato alla sub WS_AvviaConversioneCompleted (per utilizzare il WS mi sembra di capire che hai aggiunto un componente nel form e lo hai chiamato WS - è così?).

Mi sembra di capire che tutto funzioni come qui riepilogato solo che non ricevi mai l'evento di WS_AvviaConversioneCompleted.

Scusa se comincio dalle domande più banali ma prima di tutto dovresti essere sicuro che "AvviaConversione" si concluda correttamente.

Poi dovresti controllare l'attributo Async="true" nella direttiva della pagina che gestisce il tuo WS (<%@ Page ... nel file .asmx).

Tra l'altro trovi un banalissimo esempio nelle ASP.NET Web Services QuickStarts di MSDN.

Fammi sapere come procede questo caso.

Ciao.

.:. Marcello Rutter .:.
19 messaggi dal 26 maggio 2006
mmmm... forse ti ho portato un po' fuori strada....
allora vediamo di spiegarlo così.

Ho un webservice che deve effettuare delle conversioni di alcuni file. A fronte di una chiamata esegue due operazioni

1) Effettua dei calcoli per verificare che la conversione sia fattibile (tempo di esecuzione: circa 1 secondo)
2) Se il punto 1 è true effettua una conversione dei file (tempo di esecuzione: circa 10 minuti)

Il programma client lancia il webmethod e si aspetta di ottenere un risultato True o False a seconda se l'operazione di conversione è fattibile o meno (ovvero il risultato del punto 1)

Ma al client non interessa se l'operazione di conversione è conclusa o meno (punto 2) interessa solo sapere se è fattibile. quindi non posso tenere l'utente appeso per tutto il tempo di esecuzione ma solo per il tempo necessario al punto 1.

Quello che avevo pensato di fare è:
lancio il webmethod, il webmethod esegue il controllo e lancia un thread separato per la conversione e poi esce restituendo all'utente il risultato lasciando il thread di conversione a lavorare.

Di tutto questo il webmethod funziona benissimo. I calcoli vanno, il thread secondario di conversione funziona benissimo e viene chiamato in maniera asincrona. Viene completata l'esecuzione di tutto il codice del webmethod ma la Response da rispedire al client rimane appesa fina al termine del secondo punto quando il thread secondario ha finito. Il client non è bloccato perchè la chiamata E' asincrona ma il client riceve risposta del webmethod non dopo 1 secondo come vorrei (solo punto 1) ma dopo 10 minuti di esecuzione, dopo aver eseguito anche il punto 2
19 messaggi dal 26 maggio 2006
Per quanto riguarda le domande che mi hai fatto

Ciao.

Partiamo dal secondo esempio. Mi sembra di capire che

WS.AvviaConversioneAsync() 


funzioni, nel senso che il metodo esce immediatamente senza attendere che il webmethod termini il proprio lavoro (mi confermi che è così?).


Si è così... mi verrà scatenato l'evento WS_AvviaConversioneCompleted al completamento del webmethod




Ora, nel WebMethod dovresti chiamare "DPPConvert" senza thread o altro:

<WebMethod()> _ 
Public Function AvviaConversione() As Boolean 
dim bCanConvert as boolean 

'... Serie di calcoli 
bCanConverter = true 

if bCanConverter Then 
DPPConvert()
End If 

Return bCanConverter 
End Function


Al termine dell'esecuzione del WS nel server web dovrebbe arrivarti l'evento associato alla sub WS_AvviaConversioneCompleted (per utilizzare il WS mi sembra di capire che hai aggiunto un componente nel form e lo hai chiamato WS - è così?).

Mi sembra di capire che tutto funzioni come qui riepilogato solo che non ricevi mai l'evento di WS_AvviaConversioneCompleted.


WS non è un componente ma è il nome del webservice che utilizzo.
Ricevo correttamente l'evento WS_AvviaConversioneCompleted al termine del webmethod ma come ti dicevo prima dopo 10 minuti e non dopo 1 secondo

Nota: se fai un webservice con il 2.0 ti crea una struttura diversa da quella dell'1.1.... Su l'1.1 avevi BeginInvoke che con addressof gli indicavi la callback. Con il 2.0 invece hai il metodo Async che ti scatena l'evento Completed... Il metodo AvviaConversioneAsync e l'evento WS_AvviaConversioneCompleted non l'ho creati io ma il compilatore. Io ho creato solo il metodo AvviaConversione. E' una struttura leggermente diversa dall'1.1




Poi dovresti controllare l'attributo Async="true" nella direttiva della pagina che gestisce il tuo WS (<%@ Page ... nel file .asmx).


Tutto ok su quel lato

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.