Come si evince da
questo comunicato stampa la prossima versione di JWSDP supporterà non solo WS-I BP1, ma anche WS-Security in versione OASIS ... che sia la volta buona per avere dei Web Service sicuri e interoperabili tra Java e .NET? ... Lo spero ardentemente!
Link:
http://biz.yahoo.com/prnews/040527/sfth050_1.html
Da poco più di un mese è nato un libro a proposito di uno dei prodotti che più apprezzo tra le novità introdotte da Office 2003: InfoPath!
I miei complimenti a Pierre Greborio che è uno dei due autori!
Link:
http://www.wrox.com/books/0764557130.shtml
Ho appena visto che Christoph Schittko, un ragazzo molto in gamba che ho avuto il piacere di conoscere lo scorso anno ad ottobre a PDC, ha pubblicato su MSDN un articolo a proposito dei più comuni problemi legati allo sviluppo con XmlSerializer ... ovviamente con le soluzioni.
Bravo Christoph, ottimo articolo!
Con un pizzico di soddisfazione ho appena scoperto che Scott Woodgate's ha annunciato il programma beta per un adapter BizTalk 2004 per WSE2. Il pizzico :-) di soddisfazione e soprattutto il piacere (da appassionato di BizTalk e di WSE2) è che a ottobre dello scorso anno avevo parlato, a PDC2003, con ScottW proprio a proposito di un adapter per WSE2 e ci eravamo poi sentiti con un paio di email per approfondire il perchè di una mia simile esigenza. Meno male! Evidentemente non ero il solo a desiderare un adapter simile :-) ! Inutile dire che non vedo l'ora di poterlo scaricare e provare ...
Link:
http://blogs.msdn.com/scottwoo/archive/2004/05/24/140500.aspx
E' disponibile su MSDN Subscribers download una nuova versione di VS.NET 2005. Se non la smettono di rilasciare nuove versioni ;-) di tutto ogni poco ... giuro che cambio lavoro :-D !!!
Ok ora sto "tentando" di scaricarlo ....
Link:
http://msdn.microsoft.com/vs2005/
Steve Ballmer nella sua keynote di oggi a TechEd ha annunciato il rilascio della versione finale di WSE2!!!
Ma vieniiiiiii!!!!! :-)
Le novità sono tante, soprattutto sul fronte del messaging e della gestione della sicurezza in modo pressoché "automatico".
State sintonizzati su questo canale ... a brevissimo arriverà del materiale utile a tal proposito!!!!
Birdge The Gap!
Link:
http://msdn.microsoft.com/webservices/
Ho letto un post di Andrea Zani, che ho avuto il piacere di conoscere qualche giorno fa, in cui espone il risultato di alcune verifiche che ha fatto con .NET Reflector per capire il comportamento di SyncLock di VB.NET e lock di C# rispetto all'uso autonomo e manuale di Monitor.Enter() ... Monitor.Exit(), in particolare nel caso in cui vi siano dei blocchi try..catch attorno al lock o al monitor del caso.
Rifaccio il discorso solo in C# e provo a darmi una risposta alla domanda che Andrea lascia aperta: "E' restata immutata, più veloce e più leggibile. Quali sono dunque le conclusioni di questo blog? Boh! Chi aveva ragione? Mah... :)":
using System;
using System.Threading;
public class TestLock
{
static Object test;
static void Main()
{
test = new Object();
usaLock();
usaLockWithCatchBlock();
usaMonitor();
usaMonitorWithCatchBlock();
}
static void usaLock()
{
lock(test)
{
Console.WriteLine("Faccio qualcosa...");
}
}
static void usaMonitor()
{
Monitor.Enter(test);
try
{
Console.WriteLine("Faccio qualcosa...");
}
finally
{
Monitor.Exit(test);
}
}
static void usaLockWithCatchBlock()
{
try
{
lock(test)
{
Console.WriteLine("Faccio qualcosa...");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static void usaMonitorWithCatchBlock()
{
try
{
Monitor.Enter(test);
try
{
Console.WriteLine("Faccio qualcosa...");
}
finally
{
Monitor.Exit(test);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Il risultato analizzato con ILDASM (per fugare ogni dubbio relativo a qualche possibile fraintendimento di .NET Reflector) è il seguente:
.class public auto ansi beforefieldinit TestLock
extends [mscorlib]System.Object
{
.field private static object test
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 31 (0x1f)
.maxstack 1
IL_0000: newobj instance void [mscorlib]System.Object::.ctor()
IL_0005: stsfld object TestLock::test
IL_000a: call void TestLock::usaLock()
IL_000f: call void TestLock::usaLockWithCatchBlock()
IL_0014: call void TestLock::usaMonitor()
IL_0019: call void TestLock::usaMonitorWithCatchBlock()
IL_001e: ret
} // end of method TestLock::Main
.method private hidebysig static void usaLock() cil managed
{
// Code size 32 (0x20)
.maxstack 2
.locals init (object V_0)
IL_0000: ldsfld object TestLock::test
IL_0005: dup
IL_0006: stloc.0
IL_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
.try
{
IL_000c: ldstr "Faccio qualcosa..."
IL_0011: call void [mscorlib]System.Console::WriteLine(string)
IL_0016: leave.s IL_001f
} // end .try
finally
{
IL_0018: ldloc.0
IL_0019: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_001e: endfinally
} // end handler
IL_001f: ret
} // end of method TestLock::usaLock
.method private hidebysig static void usaMonitor() cil managed
{
// Code size 34 (0x22)
.maxstack 1
IL_0000: ldsfld object TestLock::test
IL_0005: call void [mscorlib]System.Threading.Monitor::Enter(object)
.try
{
IL_000a: ldstr "Faccio qualcosa..."
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
IL_0014: leave.s IL_0021
} // end .try
finally
{
IL_0016: ldsfld object TestLock::test
IL_001b: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0020: endfinally
} // end handler
IL_0021: ret
} // end of method TestLock::usaMonitor
.method private hidebysig static void usaLockWithCatchBlock() cil managed
{
// Code size 48 (0x30)
.maxstack 2
.locals init (class [mscorlib]System.Exception V_0,
object V_1)
.try
{
IL_0000: ldsfld object TestLock::test
IL_0005: dup
IL_0006: stloc.1
IL_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
.try
{
IL_000c: ldstr "Faccio qualcosa..."
IL_0011: call void [mscorlib]System.Console::WriteLine(string)
IL_0016: leave.s IL_001f
} // end .try
finally
{
IL_0018: ldloc.1
IL_0019: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_001e: endfinally
} // end handler
IL_001f: leave.s IL_002f
} // end .try
catch [mscorlib]System.Exception
{
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: callvirt instance string [mscorlib]System.Exception::get_Message()
IL_0028: call void [mscorlib]System.Console::WriteLine(string)
IL_002d: leave.s IL_002f
} // end handler
IL_002f: ret
} // end of method TestLock::usaLockWithCatchBlock
.method private hidebysig static void usaMonitorWithCatchBlock() cil managed
{
// Code size 50 (0x32)
.maxstack 2
.locals init (class [mscorlib]System.Exception V_0)
.try
{
IL_0000: ldsfld object TestLock::test
IL_0005: call void [mscorlib]System.Threading.Monitor::Enter(object)
.try
{
IL_000a: ldstr "Faccio qualcosa..."
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
IL_0014: leave.s IL_0021
} // end .try
finally
{
IL_0016: ldsfld object TestLock::test
IL_001b: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0020: endfinally
} // end handler
IL_0021: leave.s IL_0031
} // end .try
catch [mscorlib]System.Exception
{
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: callvirt instance string [mscorlib]System.Exception::get_Message()
IL_002a: call void [mscorlib]System.Console::WriteLine(string)
IL_002f: leave.s IL_0031
} // end handler
IL_0031: ret
} // end of method TestLock::usaMonitorWithCatchBlock
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method TestLock::.ctor
} // end of class TestLock
Nei metodi privi di un try...catch loro si vede in modo chiaro che non c'è una reale differenza. Sì in effetti il caso basato su lock alloca uno stack maggiore, perchè viene dichiarata una variabile System.Object locale per contenere il riferimento all'oggetto statico sul quale faccio il lock. Nel caso di blocco try...catch con all'intero un lock o in alternativa un Monitor.Enter()...Monitor.Exit() non mi sembra però che ci sia differenza. Cioè il compilatore produce codice pressoché identico.
D'altra parte la soluzione del try...finally "secco" annidato in un try...catch esterno sappiamo essere generalmente migliore in quanto rilascia le risorse critiche prima della gestione dell'errore. Altrimenti il rischio è che, in situazioni in cui il blocco catch svolge attività impegnative (salvataggio di eventi su file o su eventlog, invio di email, ecc.) la nostra risorsa rimane impegnata inutilmente.
Quindi lock e SyncLock sono comodi e fanno la stessa cosa di Monitor.Enter()...Monitor.Exit(), a patto che se decidiamo di usare Monitor ci ricordiamo di costruire bene il codice, come di seguito ripetuto:
try
{
Monitor.Enter(test);
try
{
Console.WriteLine("Faccio qualcosa...");
}
finally
{
Monitor.Exit(test);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Evitiamo, in generale, situazioni come questa:
Monitor.Enter(test);
try
{
Console.WriteLine("Faccio qualcosa...");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Monitor.Exit(test);
}
In particolare se nel blocco catch svolgiamo attività impegnative e/o durature nel tempo.
Ancor peggio poi sarebbe una situazione come la seguente:
Monitor.Enter(test1);
Monitor.Enter(test2);
try
{
Console.WriteLine("Faccio qualcosa...");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Monitor.Exit(test2);
Monitor.Exit(test1);
}
Ogni blocco Monitor.Enter()...Monitor.Exit() infatti deve avere un suo try...finally ad hoc. La soluzione corretta è quindi:
try
{
Monitor.Enter(test1);
try
{
Monitor.Enter(test2);
try
{
Console.WriteLine("Faccio qualcosa...");
}
finally
{
Monitor.Exit(test2);
}
}
finally
{
Monitor.Exit(test1);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Beh? Ma non sarebbe a 'sto punto meglio fare semplicemente:
try
{
lock(test1)
{
lock(test2)
{
Console.WriteLine("Faccio qualcosa...");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Ci sono ulteriori dettagli, da non sottovalutare, sul corretto e uguale ordine di applicazione dei lock in tutte le porzioni di codice, per evitare deadlock. Inoltre è molto opinabile il catch della Exception generica ... ma per tutte queste considerazioni c'è il libro di Marco Russo che è stato pubblicato apposta :-) !
A questo punto vorrei un parere anche dall'uomo CLR e multi-thread per eccellenza: Marco Russo. Marco hai 5 minuti per darci il tuo verdetto? :-)