Modalità flusso di lavoro: Informazioni su Windows Workflow Foundation
David Chappell
Chappell & Associates
Aprile 2009
Scaricare questo articolo
Introduzione a Windows Workflow Foundation
Tutti coloro che scrivono codice vogliono creare un ottimo software. Se il software è un'applicazione server, parte di essere grande è il ridimensionamento corretto, la gestione di carichi di grandi dimensioni senza consumare troppe risorse. Una grande applicazione dovrebbe anche essere il più facile possibile capire, sia per i suoi creatori che per le persone che la mantengono.
Raggiungere entrambi questi obiettivi non è facile. Gli approcci che consentono la scalabilità delle applicazioni tendono a suddividerli, dividendo la logica in blocchi separati che possono essere difficili da comprendere. La scrittura di una logica unificata che vive in un singolo eseguibile può tuttavia rendere impossibile il ridimensionamento dell'applicazione. Ciò che serve è un modo per mantenere unificata la logica dell'applicazione, rendendola più comprensibile, consentendo comunque la scalabilità dell'applicazione.
Raggiungere questo obiettivo principale di Windows Workflow Foundation (WF). Supportando la logica creata usando flussi di lavoro, WF offre una base per la creazione di applicazioni unificate e scalabili. Oltre a questo, WF può anche semplificare altre sfide di sviluppo, ad esempio coordinare il lavoro parallelo, tenere traccia dell'esecuzione di un programma e altro ancora.
WF è stato rilasciato per la prima volta con .NET Framework 3.0 nel 2006, quindi aggiornato in .NET Framework 3.5. Queste prime due versioni erano utili, soprattutto per i fornitori di software indipendenti (ISV), ma non sono diventate tecnologie mainstream per gli sviluppatori aziendali. Con la versione di WF che fa parte di .NET Framework 4, i suoi creatori hanno lo scopo di cambiare questo aspetto. L'obiettivo principale di questa versione più recente è quello di rendere WF una parte standard del toolkit di programmazione per tutti gli sviluppatori .NET.
Come qualsiasi tecnologia, l'applicazione di WF richiede la comprensione di ciò che è, perché è utile e quando ha senso usarlo. L'obiettivo di questa panoramica è rendere chiare queste cose. Non si apprenderà come scrivere applicazioni WF, ma si vedrà cosa offre WF, perché è il modo in cui è e come può migliorare la vita di uno sviluppatore. In altre parole, si inizierà a comprendere il modo del flusso di lavoro.
La sfida: Scrittura di logica dell'applicazione unificata e scalabile
Un modo semplice per scrivere un programma consiste nel creare un'applicazione unificata che viene eseguita in un singolo processo in un singolo computer. La figura 1 illustra questa idea.
figura 1: la logica dell'applicazione può essere creata come un intero unificato, quindi eseguita in un determinato thread in un processo in esecuzione in un singolo computer.
Lo pseudo-codice semplice in questo esempio illustra i tipi di operazioni eseguite in genere dalle applicazioni:
- Mantenere lo stato, rappresentato da una variabile stringa semplice.
- Ottenere l'input dal mondo esterno, ad esempio ricevendo una richiesta da un client. Una semplice applicazione potrebbe semplicemente leggere dalla console, mentre un esempio più comune potrebbe ricevere una richiesta HTTP da un Web browser o un messaggio SOAP da un'altra applicazione.
- Inviare l'output al mondo esterno. A seconda della modalità di compilazione, l'applicazione potrebbe eseguire questa operazione tramite HTTP, un messaggio SOAP, scrivendo nella console o in altro modo.
- Fornire percorsi alternativi tramite la logica usando istruzioni del flusso di controllo, ad esempio if/else e while.
- Eseguire il codice appropriato in ogni punto dell'applicazione.
Nell'approccio unificato illustrato di seguito, la logica dell'applicazione impiega tutta la durata in esecuzione su un thread all'interno di un processo specifico in un singolo computer. Questo approccio semplice presenta diversi vantaggi. Per un aspetto, la logica può essere implementata in modo semplice e unificato. Ciò consente agli utenti che lavorano con il codice di comprenderlo e rende esplicito anche l'ordine di eventi consentito. Nella figura 1, ad esempio, è evidente che la prima richiesta del client deve precedere la seconda: il flusso di controllo del programma lo richiede. Quando arriva la seconda richiesta, non è necessario verificare che la prima richiesta sia già stata gestita, poiché non esiste un altro percorso attraverso l'applicazione.
Un altro vantaggio di questo approccio è che l'uso dello stato dell'applicazione è semplice. Tale stato viene mantenuto nella memoria del processo e, poiché il processo viene eseguito continuamente fino a quando non viene eseguito il lavoro, lo stato è sempre disponibile: lo sviluppatore accede solo alle variabili normali. Cosa potrebbe essere più semplice?
Tuttavia, questo stile di programmazione di base presenta limitazioni. Quando l'applicazione deve attendere l'input, indipendentemente dal fatto che un utente nella console, un client di servizi Web o qualcos'altro, in genere si blocchi. Sia il thread che il processo in uso verranno mantenuti fino all'arrivo dell'input, ma il tempo necessario. Poiché i thread e i processi sono risorse relativamente scarse, le applicazioni che si trovano in uno solo quando sono solo in attesa di input non sono molto scalabili.
Un approccio più scalabile consiste nell'arrestare l'applicazione quando è in attesa di input, quindi riavviarlo all'arrivo dell'input. Questo approccio non comporta lo spreco di risorse, perché l'applicazione non è in possesso di un thread o di un processo quando non ne ha bisogno. In questo modo, l'applicazione viene eseguita anche in processi diversi in computer diversi in momenti diversi. Invece di essere bloccato in un singolo sistema, come nella figura 1, l'applicazione può essere invece eseguita in uno dei diversi computer disponibili. Ciò consente anche la scalabilità, poiché il lavoro può essere distribuito più facilmente tra computer diversi. La figura 2 mostra l'aspetto.
figura 2: La logica dell'applicazione può essere suddivisa in blocchi, tutti gli stati comuni di condivisione, che possono essere eseguiti in computer diversi.
Questa applicazione di esempio contiene la stessa logica di prima, ma ora è suddivisa in blocchi separati. Quando viene ricevuta la prima richiesta del client, il blocco appropriato viene caricato ed eseguito. Dopo che questa richiesta è stata gestita e una risposta inviata di nuovo, questo blocco può essere scaricato. Non è necessario che rimangano in memoria. Quando arriva la seconda richiesta del client, il blocco che lo gestisce viene caricato ed eseguito. Come illustrato nella figura 2, questo blocco può essere eseguito in un thread diverso in un processo diverso in esecuzione in un computer diverso dal primo blocco. Dopo aver gestito la richiesta, questo secondo blocco può anche essere scaricato, liberando qualsiasi memoria usata.
Un esempio comune di una tecnologia che funziona in questo modo è ASP.NET. Uno sviluppatore implementa un'applicazione ASP.NET come set di pagine, ognuna contenente parte della logica dell'applicazione. Quando arriva una richiesta, la pagina corretta viene caricata, eseguita e quindi scaricata di nuovo.
Un'applicazione compilata in questo stile può usare le risorse del computer in modo più efficiente rispetto a una creata usando l'approccio più semplice illustrato in precedenza e quindi la scalabilità migliorerà. Tuttavia, abbiamo pagato per questo miglioramento della scalabilità con complessità. Per un aspetto, i vari blocchi di codice devono in qualche modo condividere lo stato, come illustrato nella figura 2. Poiché ogni blocco viene caricato su richiesta, eseguito, quindi arrestato, questo stato deve essere archiviato esternamente, ad esempio in un database o in un altro archivio di persistenza. Invece di accedere alle variabili normali, come lo scenario illustrato nella figura 1, uno sviluppatore deve ora eseguire operazioni speciali per acquisire e salvare lo stato dell'applicazione. Nelle applicazioni ASP.NET, ad esempio, gli sviluppatori possono scrivere lo stato direttamente in un database, accedere all'oggetto Session o usare un altro approccio.
Un altro costo di questa scalabilità migliorata è che il codice non fornisce più una visualizzazione unificata della logica complessiva del programma. Nella versione illustrata nella figura 1, l'ordine in cui il programma prevede l'input è ovvio, c'è un solo percorso possibile attraverso il codice. Con la versione della figura 2, tuttavia, questo flusso di controllo non è evidente. In effetti, il blocco di codice che gestisce la seconda richiesta del client potrebbe dover iniziare verificando che la prima richiesta sia già stata eseguita. Per un'applicazione che implementa qualsiasi tipo di processo aziendale significativo, la comprensione e l'implementazione corretta del flusso di controllo in vari blocchi possono risultare difficili.
La situazione è questa: la scrittura di applicazioni unificate semplifica la vita dello sviluppatore e il codice è semplice da comprendere, ma il risultato non è scalabile correttamente. La scrittura di applicazioni in blocchi che condividono lo stato esterno, ad esempio le applicazioni ASP.NET, consente la scalabilità, ma rende più difficile la gestione dello stato e perde il flusso di controllo unificato. È possibile eseguire entrambe le operazioni: scrivere logica di business scalabile con una gestione semplice dello stato, ma avere ancora una visualizzazione unificata del flusso di controllo dell'applicazione.
Questo è esattamente ciò che fornisce il flusso di lavoro. Nella sezione successiva viene illustrato come.
La soluzione: modalità del flusso di lavoro
Comprendere in che modo un'applicazione WF risolve questi problemi (e altri) richiede un'analisi dettagliata delle nozioni di base sul funzionamento di WF. Lungo il percorso, vedremo perché questa tecnologia può migliorare la vita per gli sviluppatori in un numero sorprendentemente elevato di casi.
Creazione di una logica dell'applicazione unificata
Un'applicazione basata su flusso di lavoro creata con WF esegue gli stessi tipi di operazioni di un'applicazione normale: mantiene lo stato, ottiene l'input e invia l'output al mondo esterno, fornisce il flusso di controllo ed esegue il codice che esegue il lavoro dell'applicazione. In un flusso di lavoro di WF, tuttavia, tutte queste operazioni vengono eseguite dalle attività. La figura 3 mostra l'aspetto, con l'approccio unificato al codice illustrato insieme al confronto.
figura 3: in un flusso di lavoro di WF, tutte le attività di un programma vengono eseguite dalle attività.
Come illustrato nella figura 3, ogni flusso di lavoro ha un'attività più esterna che contiene tutte le altre. In questo caso, questa attività più esterna è denominata Sequence e, come un programma ordinario, può avere variabili che mantengono lo stato. Poiché Sequence è un'attività composita, può anche contenere altre attività.
In questo semplice esempio, il flusso di lavoro inizia con un'attività ReceiveMessage che ottiene l'input dall'esterno. Questo è seguito da un'attività If, che (senza sorpresa) implementa un ramo. Se è anche un'attività composita, contenente altre attività (con etichetta X e Y qui) che eseguono il lavoro eseguito in ogni ramo. L'attività If è seguita da un'attività SendMessage che invia un output al mondo oltre questo flusso di lavoro. Viene visualizzata un'altra attività ReceiveMessage successiva, che ottiene più input, quindi viene seguita da un'attività While. Mentre contiene un'altra attività, Z, che esegue il lavoro di questo ciclo while. L'intero flusso di lavoro termina con un'attività SendMessage finale, inviando il risultato finale del programma.
Tutte queste attività corrispondono funzionalmente a varie parti di un programma tipico, come suggerisce i colori corrispondenti nella figura 2. Ma invece di usare elementi del linguaggio predefiniti, come fa un programma tradizionale, ogni attività in un flusso di lavoro WF è in realtà una classe. L'esecuzione del flusso di lavoro viene eseguita dal runtime di WF, un componente che sa come eseguire le attività. La figura 4 illustra questa idea.
figura 4: il runtime di WF esegue le attività nell'ordine determinato dal flusso di lavoro.
Quando inizia a eseguire un flusso di lavoro, il runtime di WF esegue prima l'attività più esterna, che in questo esempio è una sequenza. Esegue quindi la prima attività all'interno di quella, che qui è ReceiveMessage, seguita dall'attività successiva e così via. Esattamente quali attività vengono eseguite in una determinata situazione dipendono da quale percorso viene eseguito attraverso il flusso di lavoro. Ad esempio, il recupero di un tipo di input nella prima attività ReceiveMessage potrebbe causare l'attività If per l'esecuzione dell'attività X, mentre un altro tipo di input potrebbe causare l'esecuzione dell'attività Y. È come qualsiasi altro programma.
È importante comprendere che il runtime di WF non conosce affatto gli elementi interni delle attività in esecuzione. Non è in grado di indicare un valore If da receiveMessage. L'unica cosa che sa fare è eseguire un'attività, quindi eseguire quella successiva. Il runtime può vedere i limiti tra le attività, tuttavia, che come si vedrà è una cosa utile.
Un aspetto importante di questo è che WF non definisce alcun linguaggio specifico per descrivere i flussi di lavoro, tutto dipende dalle attività che uno sviluppatore sceglie di usare. Per semplificare la vita, WF include una libreria di attività di base (BAL) che fornisce un set di attività ampiamente utile. (Tutte le attività di esempio usate qui sono tratte dal BAL, in effetti. Tuttavia, gli sviluppatori sono liberi di creare qualsiasi altra attività che gli piace. Possono anche scegliere di ignorare completamente il BAL.
C'è una domanda ovvia qui: Perché andare a tutti questi problemi? La creazione di un programma che usa attività è diversa da quella usata dagli sviluppatori, quindi perché qualcuno dovrebbe preoccuparsi? Perché non scrivere semplicemente codice ordinario?
La risposta, naturalmente, è che questo approccio può essere utile per creare codice migliore. Si noti, ad esempio, che il flusso di lavoro fornisce allo sviluppatore un flusso di controllo unificato. Come nel caso semplice illustrato nella figura 1, la logica principale del programma è definita in un unico flusso coerente. In questo modo è più semplice comprendere e, poiché la logica non è suddivisa in blocchi, non è necessario alcun controllo aggiuntivo. Il flusso di lavoro stesso esprime il flusso di controllo consentito.
Questo rappresenta la metà dell'obiettivo: creare una logica unificata dell'applicazione. Tuttavia, le applicazioni WF possono anche eseguire la seconda metà, creando applicazioni scalabili con gestione dello stato semplice. Nella sezione successiva viene illustrato il modo in cui il flusso di lavoro rende possibile questa operazione.
Scalabilità
Per essere scalabile, un'applicazione server non può essere bloccata in un singolo processo in un singolo computer. Tuttavia, suddivide in modo esplicito la logica dell'applicazione in blocchi, come in ASP.NET pagine, suddivide ciò che deve essere un flusso di controllo unificato. Forza inoltre il programmatore a lavorare in modo esplicito con lo stato. È un modo per suddividere automaticamente la logica in blocchi che possono essere eseguiti in processi diversi in computer diversi. Si vuole anche gestire lo stato dell'applicazione, quindi è necessario eseguire tutte le variabili di accesso.
Questo è esattamente ciò che forniscono i flussi di lavoro. La figura 5 mostra i concetti fondamentali di come WF esegue queste operazioni.
figura 5: il runtime di WF scarica un flusso di lavoro mentre è in attesa dell'input, quindi lo carica nuovamente una volta che arriva l'input.
Come qualsiasi applicazione, un flusso di lavoro WF blocca l'attesa dell'input. Nella figura 5, ad esempio, il flusso di lavoro viene bloccato alla seconda attività ReceiveMessage in attesa della seconda richiesta del client (passaggio 1). Il runtime di WF rileva questa situazione e quindi archivia lo stato del flusso di lavoro e indica dove deve essere ripreso il flusso di lavoro in un archivio di persistenza (passaggio 2). Quando arriva l'input per questo flusso di lavoro (passaggio 3), il runtime di WF trova lo stato persistente, quindi ricarica il flusso di lavoro, raccogliendo l'esecuzione in cui è stata interrotta (passaggio 4). Tutto questo avviene automaticamente: lo sviluppatore WF non deve eseguire alcuna operazione. Poiché il runtime di WF può visualizzare nel flusso di lavoro, può gestire tutti questi dettagli.
Un vantaggio evidente di questo approccio è che il flusso di lavoro non si blocca nella memoria bloccando un thread e usando un processo mentre è in attesa di input. Un altro vantaggio è che un flusso di lavoro persistente può potenzialmente essere ricaricato in un computer diverso da quello in cui era in esecuzione originariamente. Per questo motivo, diverse parti del flusso di lavoro potrebbero finire in esecuzione in sistemi diversi, come illustrato nella figura 6.
figura 6: un flusso di lavoro può essere eseguito su thread diversi, in processi diversi e in computer diversi durante la sua durata.
In questo esempio si supponga che il flusso di lavoro gestisca la prima richiesta client in un processo nel computer A. Quando il secondo ReceiveMessage impedisce al flusso di lavoro di bloccare l'attesa dell'input, il runtime di WF scaricherà lo stato del flusso di lavoro in un archivio di persistenza, come appena descritto. Quando arriva la seconda richiesta del client, è possibile che questo flusso di lavoro venga ricaricato in un processo nel computer B. Anziché essere bloccato in un thread specifico in un processo specifico in un computer specifico, un flusso di lavoro WF può essere spostato in base alle esigenze. E lo sviluppatore ottiene gratuitamente questa agilità, viene fornita automaticamente da WF.
Vale la pena sottolineare che il runtime di WF non è importante per quanto tempo il flusso di lavoro deve attendere l'input. Potrebbe arrivare qualche secondo dopo che il flusso di lavoro viene salvato in modo permanente, alcuni minuti dopo o anche alcuni mesi dopo. Finché l'archivio di persistenza rimane nello stato del flusso di lavoro, tale flusso di lavoro può essere riavviato. Ciò rende WF una tecnologia interessante per la creazione di applicazioni che implementano processi a esecuzione prolungata. Si pensi a un'applicazione che supporta un processo di assunzione, ad esempio, che comprende tutto, dalla pianificazione dei colloqui iniziali all'integrazione di un nuovo dipendente nell'organizzazione. Questo processo potrebbe durare settimane o mesi e quindi la gestione dello stato dell'applicazione con WF ha un buon senso. Tuttavia, anche se WF può essere molto utile con questo tipo di processo a esecuzione prolungata, è importante comprendere che questo non è l'unico scopo. Qualsiasi applicazione che richiede logica unificata e scalabile può essere un buon candidato per WF.
Di fatto, si prenda un'altra occhiata alla figura 6. Non è molto simile alla figura 2, che ha mostrato come un'applicazione in blocchi (ad esempio, una creata esclusivamente con ASP.NET) ha ottenuto la scalabilità? In effetti, la figura 6 non ha anche una forte somiglianza con la figura 1, che ha mostrato un'applicazione unificata compilata con un flusso di controllo lineare? WF ottiene entrambi questi risultati: il flusso di controllo dell'applicazione è espresso in modo comprensibile, unificato e l'applicazione può essere ridimensionata, poiché non è bloccata in un singolo processo in un singolo computer. Questa è la bellezza del flusso di lavoro.
E questo non è tutto; l'uso di WF offre anche altri vantaggi. Può semplificare il coordinamento del lavoro parallelo, ad esempio per tenere traccia dello stato di avanzamento di un'applicazione e altro ancora. La sezione successiva esamina questi aspetti della tecnologia.
Altri vantaggi del flusso di lavoro
Un flusso di lavoro di WF è costituito da attività eseguite dal runtime di WF. Anche se la comprensione del mondo WF richiede qualche sforzo, la scrittura della logica dell'applicazione in questo stile rende più semplice una serie di problemi di programmazione comuni, come descritto di seguito.
Coordinamento del lavoro parallelo
WF BAL include attività che corrispondono alle istruzioni del linguaggio di programmazione familiari. Per questo motivo, è possibile scrivere flussi di lavoro che si comportano in modo molto simile ai programmi normali. Tuttavia, la presenza del runtime WF consente anche di creare attività che forniscono più di un linguaggio di programmazione convenzionale. Un esempio importante è l'uso di un flusso di lavoro per semplificare il coordinamento del lavoro parallelo.
Non confondere: lo stato attivo qui non riguarda la scrittura di codice parallelo che viene eseguito simultaneamente su un processore multi-core. Si pensi invece a un'applicazione che, ad esempio, deve chiamare due servizi Web, quindi attendere entrambi i risultati prima di continuare. L'esecuzione delle chiamate in parallelo è chiaramente più veloce rispetto all'esecuzione sequenziale, ma la scrittura di codice tradizionale che esegue questa operazione non è semplice. E mentre .NET Framework offre diversi approcci per effettuare queste chiamate in modo asincrono, nessuno di essi è particolarmente semplice. Si tratta di un'altra situazione in cui il flusso di lavoro può brillare: WF semplifica questa operazione. La figura 7 mostra come.
Figura 7: Attività contenute in un'esecuzione di attività parallele in parallelo.
Questa figura mostra un flusso di lavoro semplice simile all'esempio precedente. La differenza importante è che ora richiama due servizi Web, quindi attende una risposta da entrambi prima di continuare. Per eseguire queste chiamate in parallelo, l'autore del flusso di lavoro ha eseguito il wrapping di entrambe le coppie di attività SendMessage e ReceiveMessage all'interno di un'attività Parallel. Parallel è una parte standard della libreria di attività di base di WF ed esegue esattamente ciò che suggerisce il nome: esegue le attività contenute in parallelo. Invece di fare in modo che lo sviluppatore gestisca questa complessità, il runtime di WF e l'attività Parallel eseguono l'attività pesante. Tutto quello che lo sviluppatore deve fare è organizzare le attività in base alle esigenze per risolvere il problema.
Fornire il rilevamento automatico
Poiché il runtime di WF può visualizzare i limiti tra le attività di un flusso di lavoro, sa quando ognuna di queste attività inizia e termina. Dato questo, fornire il rilevamento automatico dell'esecuzione del flusso di lavoro è semplice. La figura 8 illustra questa idea.
figura 8: il runtime di WF può tenere traccia automaticamente dell'esecuzione di un flusso di lavoro.
Come illustrato in questo esempio, il runtime di WF può scrivere un record dell'esecuzione di un flusso di lavoro in un archivio di rilevamento. Un'opzione consiste nel registrare le attività, con un record scritto ogni volta che un'attività inizia e termina l'esecuzione. Al momento mostrato nella figura, ad esempio, il flusso di lavoro sta per iniziare a eseguire l'attività If e quindi il runtime di WF sta scrivendo un evento che indica questo. È anche possibile tenere traccia di variabili specifiche, ad esempio lo stato del flusso di lavoro, registrando i valori in vari punti dell'esecuzione del flusso di lavoro.
Come per altri aspetti di WF, questa registrazione automatica richiede essenzialmente nessun lavoro da parte dello sviluppatore. Può solo indicare che il tracciamento dovrebbe accadere, specificando il livello a cui è interessato, e WF si occupa del resto.
Creazione di attività personalizzate riutilizzabili
Le attività nel BAL di WF forniscono una varietà di funzioni utili. Come già illustrato, ad esempio, questo set predefinito include attività per il flusso di controllo, l'invio e la ricezione di messaggi, l'esecuzione di operazioni in parallelo e altro ancora. Tuttavia, la compilazione di un'applicazione reale richiede in genere la creazione di attività che eseguono attività specifiche di tale applicazione.
Per rendere possibile questa operazione, WF consente di creare attività personalizzate. Ad esempio, le attività con etichetta X, Y e Z nei flussi di lavoro mostrate in precedenza sono in realtà attività personalizzate, come la figura 9 rende esplicite.
figura 9: Le attività personalizzate consentono a un flusso di lavoro di eseguire attività specifiche dell'applicazione.
Le attività personalizzate possono essere semplici, eseguendo una sola attività oppure possono essere attività composite contenenti logica arbitrariamente complessa. E se sono semplici o complesse, le attività personalizzate possono essere usate in molti modi diversi. Ad esempio, un'applicazione aziendale creata con WF potrebbe implementare una logica specifica dell'applicazione come una o più attività personalizzate. In alternativa, un fornitore di software che usa WF potrebbe fornire un set di attività personalizzate per semplificare la vita dei clienti. Ad esempio, Windows SharePoint Services consente agli sviluppatori di creare applicazioni basate su WF che interagiscono con le persone tramite gli elenchi standard di SharePoint. Per semplificare questa operazione, SharePoint include attività personalizzate per la scrittura di informazioni in un elenco.
Le attività personalizzate possono essere scritte direttamente nel codice, usando C# o Visual Basic o un altro linguaggio. Possono anche essere creati combinando le attività esistenti, che consente alcune opzioni interessanti. Ad esempio, un'organizzazione potrebbe creare attività personalizzate di livello inferiore per gli sviluppatori più qualificati, quindi inserirle in funzioni aziendali di livello superiore per un uso meno tecnico da usare. Queste attività di livello superiore possono implementare qualsiasi logica di business necessaria, tutte racchiuse in una casella riutilizzabile.
Un altro modo per considerare questa situazione consiste nel visualizzare un set specifico di attività eseguite dal runtime di WF come linguaggio. Se un'organizzazione crea un gruppo di attività personalizzate che possono essere riutilizzate per risolvere problemi specifici in più applicazioni, ciò che sta realmente facendo sta creando un tipo di linguaggio specifico del dominio (DSL). Al termine di questa operazione, potrebbe essere possibile che gli utenti meno tecnici creino applicazioni WF usando questi blocchi preconfezionati di funzionalità personalizzate. Invece di scrivere nuovo codice per implementare le funzioni dell'applicazione, è possibile creare nuovi software utili solo assemblando le attività esistenti. Questo stile dsl, definito nel flusso di lavoro, può migliorare significativamente la produttività degli sviluppatori in alcune situazioni.
Rendere visibili i processi
La creazione di applicazioni con un linguaggio di programmazione tradizionale significa scrivere codice. La creazione di applicazioni con WF in genere non è abbastanza bassa. È invece possibile assemblare graficamente almeno il flusso di controllo principale di un flusso di lavoro. Per consentire questa operazione, WF include una finestra di progettazione del flusso di lavoro eseguita in Visual Studio. La figura 10 mostra un esempio.
figura 10: Progettazione flussi di lavoro, in esecuzione in Visual Studio, consente a uno sviluppatore di creare un flusso di lavoro trascinando e rilasciando attività.
Come illustrato in questo esempio, le attività disponibili per uno sviluppatore WF vengono visualizzate a sinistra. Per creare un flusso di lavoro, può assemblare queste attività nell'area di progettazione per creare qualsiasi logica richiesta dall'applicazione. Se necessario, la finestra di progettazione del flusso di lavoro di WF può essere ospitata nuovamente in altri ambienti, consentendo ad altri utenti di usare questo strumento all'interno delle proprie offerte.
Per alcuni sviluppatori, questo approccio grafico semplifica la creazione di applicazioni. Rende inoltre più visibile la logica principale dell'applicazione. Fornendo un'immagine semplice di ciò che sta succedendo, la finestra di progettazione del flusso di lavoro di WF può aiutare gli sviluppatori a comprendere più rapidamente la struttura di un'applicazione. Ciò può essere particolarmente utile per gli utenti che devono gestire le applicazioni distribuite, poiché l'apprendimento di una nuova applicazione abbastanza da modificarlo può richiedere molto tempo.
Ma che ne dici delle attività personalizzate? Non è ancora necessario scrivere codice? La risposta è sì, quindi WF consente anche l'uso di Visual Studio per creare attività personalizzate in C#, Visual Basic e altri linguaggi. Per comprendere il funzionamento, è importante comprendere come la finestra di progettazione di WF rappresenta le varie parti di un flusso di lavoro. La figura 11 mostra come viene in genere eseguita questa operazione.
figura 11: lo stato e il flusso di controllo di un flusso di lavoro vengono in genere descritti in XAML, mentre le attività personalizzate possono essere scritte nel codice.
La composizione di un flusso di lavoro di WF, ovvero le attività che contiene e il modo in cui tali attività sono correlate, viene in genere rappresentata tramite il linguaggio XAML (eXtensible Application Markup Language). Come illustrato nella figura 11, XAML fornisce un modo basato su XML per descrivere lo stato del flusso di lavoro come variabili e per esprimere le relazioni tra le attività del flusso di lavoro. In questo caso, ad esempio, il codice XAML per la sequenza di attività del flusso di lavoro più esterno contiene un'attività ReceiveMessage seguita da un'attività If, proprio come previsto.
Questa attività If contiene le attività personalizzate X e Y. Anziché essere create in XAML, queste attività vengono tuttavia scritte come classi C#. Anche se è possibile creare alcune attività personalizzate esclusivamente in XAML, la logica più specializzata viene in genere scritta direttamente nel codice. Infatti, anche se non è il solito approccio, uno sviluppatore è anche libero di scrivere flussi di lavoro interamente nel codice, l'uso di XAML non è strettamente obbligatorio.
Uso di Windows Workflow Foundation: alcuni scenari
Comprendere i meccanismi di WF è una parte essenziale della comprensione del modo del flusso di lavoro. Tuttavia, non è sufficiente: è anche necessario comprendere come usare i flussi di lavoro nelle applicazioni. Di conseguenza, questa sezione esamina come e perché WF potrebbe essere usato in alcune situazioni tipiche.
Creazione di un servizio flusso di lavoro
La creazione di logica di business come servizio spesso ha senso. Si supponga, ad esempio, che lo stesso set di funzionalità sia accessibile da un browser tramite ASP.NET, da un client Silverlight e da un'applicazione desktop autonoma. L'implementazione di questa logica come set di operazioni che possono essere richiamate da uno di questi client, ovvero come servizio, è probabilmente l'approccio migliore. L'esposizione della logica come servizio rende anche accessibile ad altre logiche, che talvolta semplificano l'integrazione dell'applicazione. Questa è l'idea di base alla base della nozione di ARCHITETTURA SOA, orientata ai servizi.
Per gli sviluppatori .NET oggi, la tecnologia di punta per la creazione di servizi è Windows Communication Foundation (WCF). Tra le altre cose, WCF consente agli sviluppatori di implementare la logica di business accessibile tramite REST, SOAP e altri stili di comunicazione. E per alcuni servizi, WCF può essere tutto ciò che è necessario. Se si implementa un servizio in cui ogni operazione si trova da sola, ad esempio qualsiasi operazione può essere chiamata in qualsiasi momento, senza alcun ordinamento richiesto, la compilazione di tali servizi come servizi WCF non elaborati è sufficiente. L'autore di un servizio le cui operazioni espongono solo i dati potrebbe essere in grado di evitare solo l'uso di WCF, ad esempio.
Per situazioni più complesse, tuttavia, in cui le operazioni in un servizio implementano un set correlato di funzionalità, WCF da solo potrebbe non essere sufficiente. Pensa alle applicazioni che consentono ai clienti di prenotare prenotazioni in anteprima o di effettuare acquisti online o di svolgere un altro processo aziendale. In casi come questi, è possibile scegliere di usare WF per implementare la logica del servizio. Questa combinazione ha anche un nome: la logica implementata usando WF ed esposta tramite WCF è nota come servizio flusso di lavoro. La figura 12 illustra l'idea.
figura 12: un servizio flusso di lavoro usa WCF per esporre la logica basata su WF.
Come illustrato nella figura, WCF consente di esporre uno o più endpoint che i client possono richiamare tramite SOAP, REST o altro. Quando il client chiama l'operazione iniziale in questo servizio di esempio, la richiesta viene gestita dalla prima attività ReceiveMessage del flusso di lavoro. Viene visualizzata un'attività If successiva e quale delle attività personalizzate contenute viene eseguita dipende dal contenuto della richiesta del client. Al termine dell'istruzione If, viene restituita una risposta tramite SendMessage. La seconda richiesta del client, richiamando un'altra operazione, viene gestita in modo analogo: viene accettata da receiveMessage, elaborata dalla logica del flusso di lavoro, quindi ha risposto all'uso di un oggetto SendMessage.
Perché creare una logica di business orientata ai servizi in questo modo è una buona idea? La risposta è ovvia: consente di creare un'applicazione unificata e scalabile. Invece di richiedere a ogni operazione di contenere controlli, è legale richiamarmi in questo momento? Questa conoscenza è incorporata nella logica del flusso di lavoro stessa. In questo modo l'applicazione risulta più semplice da scrivere e, altrettanto importante, più facile da comprendere per le persone che devono infine gestirla. Invece di scrivere codice personalizzato per gestire la scalabilità e la gestione dello stato, il runtime di WF esegue automaticamente queste operazioni.
Un servizio flusso di lavoro ottiene anche tutti i vantaggi descritti in precedenza, proprio come qualsiasi altra applicazione WF. Di seguito sono riportati i seguenti:
- L'implementazione di servizi che eseguono operazioni parallele è semplice: è sufficiente eliminare le attività in un'attività parallela.
- Il rilevamento viene fornito dal runtime.
- A seconda del dominio del problema, potrebbe essere possibile creare attività personalizzate riutilizzabili da usare in altri servizi.
- Il flusso di lavoro può essere creato graficamente, con la logica del processo direttamente visibile nella finestra di progettazione del flusso di lavoro di WF.
L'uso di WF e WCF insieme, ovvero la creazione di servizi flusso di lavoro, non era così facile nelle versioni precedenti di WF. Con .NET Framework 4, questa combinazione di tecnologie si riunisce in modo più naturale. L'obiettivo è creare la logica di business in questo stile il più semplice possibile.
Esecuzione di un servizio flusso di lavoro con "Dublino"
Non è stato ancora discusso un problema importante con i flussi di lavoro: dove vengono eseguiti? Il runtime di WF è una classe, come le attività. Tutti questi elementi devono essere eseguiti in un processo host, ma qual è il processo?
La risposta è che i flussi di lavoro di WF possono essere eseguiti in praticamente in qualsiasi processo. È possibile creare un host personalizzato, anche sostituendo alcuni dei servizi di base di WF (ad esempio la persistenza) se si vuole. Molte organizzazioni hanno fatto questo, soprattutto i fornitori di software. Tuttavia, la creazione di un processo host veramente funzionale per WF, completa di funzionalità di gestione, non è la cosa più semplice del mondo. E per le organizzazioni che vogliono spendere i propri soldi per la creazione di logica di business piuttosto che per l'infrastruttura, evitare questo sforzo ha senso.
Un'opzione più semplice consiste nell'ospitare un flusso di lavoro WF in un processo di lavoro fornito da Internet Information Server (IIS). Anche se funziona, fornisce solo una soluzione bare-ossa. Per semplificare la vita per gli sviluppatori WF, Microsoft sta fornendo una tecnologia denominata "Dublino". Implementato come estensioni per IIS e il servizio di attivazione dei processi di Windows (WAS), l'obiettivo principale di "Dublino" è quello di rendere IIS e WAS più attraente come host per i servizi flusso di lavoro. La figura 13 mostra l'aspetto di un servizio flusso di lavoro quando viene eseguito in un ambiente "Dublino".
figura 13: "Dublino" fornisce la gestione e altro ancora per i servizi del flusso di lavoro.
Anche se WF include meccanismi per rendere persistente lo stato, il rilevamento e altro ancora di un flusso di lavoro, fornisce solo le nozioni di base. "Dublino" si basa sul supporto intrinseco di WF per offrire un ambiente più completamente utile e gestibile. Ad esempio, insieme a un archivio di persistenza basato su SQL Server e a un archivio di rilevamento, "Dublino" fornisce uno strumento di gestione per l'uso di questi negozi. Questo strumento, implementato come estensioni di Gestione IIS, consente agli utenti di esaminare e gestire (ad esempio, terminare) flussi di lavoro salvati in modo permanente, controllare la quantità di rilevamento eseguita, esaminare i log di rilevamento e altro ancora.
Oltre alle sue aggiunte alla funzionalità esistente di WF, "Dublino" aggiunge anche altri servizi. Ad esempio, "Dublino" può monitorare le istanze del flusso di lavoro in esecuzione, riavviando automaticamente eventuali errori. L'obiettivo principale di Microsoft con "Dublino" è chiaro: fornire un set utile di strumenti e infrastrutture per la gestione e il monitoraggio dei servizi flusso di lavoro ospitati in IIS/WAS.
Uso di un servizio flusso di lavoro in un'applicazione ASP.NET
Probabilmente è giusto dire che la maggior parte delle applicazioni .NET usa ASP.NET. Rendere il flusso di lavoro mainstream, quindi, significa rendere WF un'opzione interessante per gli sviluppatori ASP.NET.
Nelle versioni precedenti di WF le prestazioni del flusso di lavoro non sono sufficienti per un numero significativo di applicazioni ASP.NET. Per la versione di .NET Framework 4, tuttavia, i progettisti di WF hanno riprogettazione parti importanti della tecnologia, aumentando significativamente le prestazioni. Questa versione, insieme all'avvento di "Dublino", rende le applicazioni basate su WF, in particolare i servizi di flusso di lavoro, un'opzione più praticabile per gli sviluppatori ASP.NET. La figura 14 mostra una semplice immagine dell'aspetto.
figura 14: la logica di business di un'applicazione ASP.NET può essere implementata come servizio del flusso di lavoro
In questo scenario, ASP.NET pagine implementano solo l'interfaccia utente dell'applicazione. La logica viene implementata interamente in un servizio flusso di lavoro. Per il servizio flusso di lavoro, l'applicazione ASP.NET è solo un altro client, mentre per l'applicazione ASP.NET, il servizio flusso di lavoro è simile a qualsiasi altro servizio. Non è necessario tenere presente che questo servizio viene implementato tramite WF e WCF.
Ancora una volta, però, la grande domanda è, perché faresti questo? Perché non scrivere semplicemente la logica dell'applicazione ASP.NET nel modo consueto? Cosa si acquista con WF (e WCF) ? A questo punto, la maggior parte delle risposte a queste domande è probabilmente ovvia, ma vale ancora la pena di ripetere:
- Anziché distribuire la logica dell'applicazione in molte pagine di ASP.NET diverse, tale logica può invece essere implementata all'interno di un singolo flusso di lavoro unificato. In particolare per i grandi siti, questo può rendere l'applicazione notevolmente più semplice da compilare e gestire.
- Anziché usare in modo esplicito lo stato nell'applicazione ASP.NET, ad esempio usando l'oggetto Session o qualcos'altro, lo sviluppatore può fare affidamento sul runtime di WF per eseguire questa operazione. L'applicazione ASP.NET deve tenere traccia solo di un identificatore di istanza per ogni istanza del flusso di lavoro (probabilmente uno per utente), ad esempio archiviandolo in un cookie. Quando l'applicazione fornisce questo identificatore a "Dublino", l'istanza del flusso di lavoro verrà ricaricata automaticamente. Inizia quindi l'esecuzione da dove è stata interrotta, con tutto lo stato ripristinato.
- Gli altri vantaggi di WF si applicano anche, tra cui il parallelismo più semplice, il rilevamento predefinito, il potenziale per le attività riutilizzabili e la possibilità di visualizzare la logica dell'applicazione.
Poiché un servizio flusso di lavoro non è associato a un processo specifico in un computer specifico, può essere bilanciato tra più istanze di "Dublino". La figura 15 mostra un esempio di come potrebbe sembrare.
figura 15: un'applicazione di ASP.NET replicata può usare più istanze di "Dublino" per eseguire un servizio flusso di lavoro.
In questo semplice scenario, le pagine di un'applicazione ASP.NET vengono replicate in tre computer server IIS. Mentre queste pagine gestiscono l'interazione con gli utenti, la logica di business dell'applicazione viene implementata come servizio del flusso di lavoro in esecuzione con "Dublino". Due istanze dell'ambiente "Dublino" sono in esecuzione, ognuna sulla propria macchina. Quando arriva la prima richiesta da un utente, un servizio di bilanciamento del carico lo instrada all'istanza superiore di IIS. La pagina ASP.NET che gestisce questa richiesta chiama un'operazione nel servizio flusso di lavoro che implementa questo blocco di logica di business. In questo modo un flusso di lavoro di WF inizia l'esecuzione nell'istanza di "Dublino" nel computer superiore della figura. Una volta completate le attività pertinenti in questo flusso di lavoro, la chiamata torna alla pagina ASP.NET e il flusso di lavoro viene salvato in modo permanente.
La seconda richiesta dell'utente viene instradata a un'istanza diversa di IIS. La pagina ASP.NET in questo computer, a sua volta, richiama un'operazione nel flusso di lavoro (persistente) in un computer diverso da quello che ha gestito la prima richiesta. Questo non è un problema: "Dublino" carica semplicemente l'istanza del flusso di lavoro dall'archivio di persistenza che condivide con il suo collega server. Questo servizio flusso di lavoro ricaricato gestisce quindi la richiesta dell'utente, raccogliendo dove è stato interrotto.
Comprendere WF (e WCF), quindi imparare a creare logica in questo nuovo stile richiede alcune operazioni. Per applicazioni ASP.NET semplici, l'arrampicata su questa curva di apprendimento potrebbe non valerne la pena. Chiunque crei applicazioni Web di grandi dimensioni usando .NET, tuttavia, deve considerare almeno la possibilità di creare la logica come servizio flusso di lavoro.
Uso dei flussi di lavoro nelle applicazioni client
Finora l'attenzione è stata interamente sull'uso di WF per creare applicazioni server. Tuttavia, sebbene questa sia la tecnologia più spesso usata oggi, WF può essere utile anche per le applicazioni client. I suoi aspetti di scalabilità in genere non aggiungono molto in questo caso, poiché il codice eseguito nei computer client in genere non deve gestire molti utenti simultanei, ma WF può comunque essere in uso.
Si consideri, ad esempio, un'applicazione client che presenta l'utente con un'interfaccia grafica creata usando Windows Form o Windows Presentation Foundation. L'applicazione avrà probabilmente gestori eventi per elaborare i clic del mouse dell'utente, probabilmente distribuendo la logica di business in questi gestori eventi. Si tratta di un'applicazione ASP.NET che estende la logica in un gruppo di pagine separate e può creare le stesse sfide. Il flusso dell'applicazione potrebbe essere difficile da distinguere, ad esempio, e lo sviluppatore potrebbe dover inserire controlli per assicurarsi che le operazioni vengano eseguite nell'ordine corretto. Analogamente a un'applicazione ASP.NET, l'implementazione di questa logica come flusso di lavoro WF unificato può aiutare a risolvere questi problemi.
Altri aspetti di WF possono essere utili anche nel client. Si supponga che l'applicazione debba richiamare più servizi Web back-end in parallelo, ad esempio o che possa trarre vantaggio dal rilevamento. Proprio come nel server, WF può aiutare a risolvere tali sfide. Sebbene la maggior parte delle applicazioni WF venga attualmente eseguita nei server, è importante riconoscere che questa non è l'unica scelta.
Un'occhiata più da vicino: la tecnologia di Windows Workflow Foundation
L'obiettivo di questa panoramica non è quello di creare uno sviluppatore di WF. Tuttavia, conoscere solo un po 'di più sulla tecnologia di WF può aiutare a decidere quando è opportuno scegliere il modo del flusso di lavoro. Di conseguenza, questa sezione esamina in modo più approfondito alcune delle parti più importanti di WF.
Tipi di flussi di lavoro
In .NET Framework 4 gli sviluppatori WF scelgono in genere tra due diversi stili di flusso di lavoro scegliendo diverse attività più esterne. Queste attività sono:
- Sequenza: esegue le attività in sequenza, una dopo l'altra. La sequenza può contenere attività If, While e altri tipi di flusso di controllo. Non è possibile tornare indietro, ma l'esecuzione deve sempre andare avanti.
- Diagramma di flusso: esegue le attività una dopo l'altra, ad esempio una sequenza, ma consente anche al controllo di tornare a un passaggio precedente. Questo approccio più flessibile, nuovo nella versione di .NET Framework 4 di WF, è più vicino al funzionamento dei processi reali e al modo in cui la maggior parte di noi pensa.
Sebbene sia Sequence che Flowchart possano fungere da attività più esterne in un flusso di lavoro, possono essere usate anche all'interno di un flusso di lavoro. In questo modo queste attività composite vengono annidate in modi arbitrari.
Nelle prime due versioni WF includeva anche un'altra opzione per l'attività più esterna di un flusso di lavoro denominata Macchina a stati. Come suggerisce il nome, questa attività consente a uno sviluppatore di creare in modo esplicito una macchina a stati, quindi di attivare attività di attivazione eventi esterni in tale macchina a stati. WF in .NET Framework 4 è tuttavia un cambiamento importante, uno che richiedeva la riscrittura della maggior parte delle attività nelle versioni precedenti e la creazione di una nuova finestra di progettazione. A causa del lavoro richiesto, gli autori di WF non distribuiranno l'attività State Machine dalla versione iniziale di .NET Framework 4. Anche le risorse di Microsoft non sono senza limiti. Tuttavia, la nuova attività Diagramma di flusso deve risolvere molte delle situazioni che in precedenza richiedevano l'uso della macchina a stati.
Libreria di attività di base
Un flusso di lavoro può contenere qualsiasi set di attività che uno sviluppatore sceglie di usare. È completamente legale, ad esempio, che un flusso di lavoro contenga attività personalizzate. Comunque, questo non è molto probabile. Nella maggior parte dei casi, un flusso di lavoro di WF userà almeno alcune delle informazioni fornite nella libreria di attività di base. Tra le attività BAL più ampiamente utili fornite da WF in .NET Framework 4 sono le seguenti:
- Assegna: assegna un valore a una variabile nel flusso di lavoro.
- Compensazione: consente di eseguire una compensazione, ad esempio la gestione di un problema che si verifica in una transazione a esecuzione prolungata.
- DoWhile: esegue un'attività, quindi controlla una condizione. L'attività verrà eseguita su e più finché la condizione è true.
- Diagramma di flusso: raggruppa un set di attività eseguite in sequenza, ma consente anche di tornare a un passaggio precedente.
- ForEach: esegue un'attività per ogni oggetto in una raccolta.
- Se: crea un ramo di esecuzione.
- Parallelo: esegue più attività contemporaneamente.
- Persistenza: richiede in modo esplicito al runtime di WF di rendere persistente il flusso di lavoro.
- Selezione: consente di attendere un set di eventi, quindi di eseguire solo l'attività associata al primo evento.
- ReceiveMessage: riceve un messaggio tramite WCF.
- SendMessage: invia un messaggio tramite WCF.
- Sequenza: raggruppa un set di attività eseguite in sequenza. Oltre a fungere da attività più esterna del flusso di lavoro, Sequence è utile anche all'interno dei flussi di lavoro. Ad esempio, un'attività While può contenere solo un'altra attività. Se tale attività è Sequence, uno sviluppatore può eseguire un numero arbitrario di attività all'interno del ciclo while.
- Switch: fornisce un ramo multi-way di esecuzione.
- Throw: genera un'eccezione.
- TryCatch: consente di creare un blocco try/catch per gestire le eccezioni.
- While: esegue una singola attività purché una condizione sia true.
Questo non è un elenco completo. WF in .NET Framework 4 include altre informazioni. Inoltre, Microsoft prevede di rendere disponibili nuove attività WF in CodePlex, il suo sito di hosting per i progetti open source. Poco dopo la versione di .NET Framework 4, ad esempio, cercare le attività che consentono ai flussi di lavoro di eseguire query e aggiornamenti del database, eseguire comandi di PowerShell e altro ancora.
Come suggerisce questo elenco, BAL riecheggia in gran parte la funzionalità di un tradizionale linguaggio di programmazione per utilizzo generico. Questo non dovrebbe essere sorprendente, poiché WF è destinato a essere una tecnologia per utilizzo generico. Come descritto in questa panoramica, tuttavia, l'approccio richiesto, ovvero le attività eseguite dal runtime di WF, possono talvolta migliorare la vita per gli sviluppatori di applicazioni.
Flusso di lavoro in .NET Framework 4
La versione 4 di .NET Framework apporta modifiche significative a Windows Workflow Foundation. Le attività nella BAL sono state riscritto, ad esempio, e alcune nuove sono state aggiunte. Ciò offre vantaggi reali, molti flussi di lavoro ora vengono eseguiti molto più velocemente, ad esempio, ma significa anche che i flussi di lavoro creati usando versioni precedenti di WF non possono essere eseguiti dalla versione .NET 4 del runtime di WF. Questi flussi di lavoro meno recenti possono comunque essere eseguiti insieme ai flussi di lavoro di .NET Framework 4 invariati, ma non devono essere buttati via. Inoltre, le attività create usando versioni precedenti di WF, inclusi interi flussi di lavoro, possono essere eseguite in una nuova attività di interoperabilità fornita da WF in .NET Framework 4. In questo modo, la logica dei flussi di lavoro meno recenti viene usata in quelle nuove.
Oltre a migliorare le prestazioni, questa nuova versione di WF apporta anche altre modifiche interessanti. Ad esempio, le versioni precedenti di WF includono un'attività Code che potrebbe contenere codice arbitrario. Questo consente a uno sviluppatore di aggiungere praticamente qualsiasi funzionalità desiderata a un flusso di lavoro, ma era una soluzione leggermente inelegante. In .NET Framework 4, gli autori di WF hanno reso la scrittura di attività personalizzate significativamente più semplici e quindi l'attività Code è stata rimossa. La nuova funzionalità viene ora creata come attività personalizzata.
Le modifiche apportate alla versione di .NET Framework 4 sono le più sostanziali rispetto all'aspetto originale di WF nel 2006. Tutti hanno lo stesso obiettivo, tuttavia: rendere più semplice per gli sviluppatori creare applicazioni efficaci usando flussi di lavoro.
Conclusione
Windows Workflow Foundation offre vantaggi reali per molte applicazioni. Nelle sue prime versioni, WF ha colpito un accordo principalmente con i fornitori di software. Queste incarnazioni originali della tecnologia erano utili, ma non erano veramente appropriate per l'uso aziendale mainstream. Con .NET Framework 4, i creatori di WF stanno cercando di modificare questa situazione.
Grazie al corretto funzionamento di WF e WCF, al miglioramento delle prestazioni di WF, alla creazione di una finestra di progettazione del flusso di lavoro migliore e all'offerta di un processo host completo con "Dublino", Microsoft rende il flusso di lavoro più attraente per un'ampia gamma di scenari. I suoi giorni come giocatore specializzato nel dramma di sviluppo di applicazioni Windows stanno disegnando verso una chiusura. WF sta andando al centro della scena.
Informazioni sull'autore
David Chappell è il principale di Chappell & Associates a San Francisco, California. Attraverso il suo discorso, la scrittura e la consulenza, aiuta le persone in tutto il mondo a comprendere, usare e prendere decisioni migliori sulla nuova tecnologia.