Accueil > > > SYNCHRONISATION DE THREADS DANS DES DLL
SYNCHRONISATION DE THREADS DANS DES DLL
Information sur la source
Description
Bonjour, Voici une petite unité qui peut s'averer tres pratique lorsque l'on a besoin de creer des threads dans une DLL. En effet, dans une DLL, la synchronisation d'évènements (Synchronize(MaMethode);) ne fonctionne pas, car la variable SyncList de l'unité Classes.pas reste locale a un module (comme n'importe quelle variable globale, d'ailleurs). Du coup, le CheckSynchronize effectué par le thread principal de l'application, dans le module principal, ne "voit" pas les évènements a synchroniser. Cette unité permet a une DLL de demander une synchronisation au module principal, qui redispatche la synchronisation aux DLL qui l'ont demandée. Voir source pour les détails.
Source
- ////////////////////////////////////////////////////////////////////////////////
- // Nom du fichier : DLLThreadSynchronize.pas //
- // Auteur : S.Mazuir //
- // Date : 10/03/2010 //
- // Révision : 1 //
- // Version : Delphi6 //
- // Plateformes : Win32 //
- // //
- // Notes : //
- // Unité permettant de gérér sans modification du code la synchronisation //
- // des évènements générés par des threads créés dans une ou plusieurs DLL. //
- // //
- // Utilisation : Ajouter cette unité au projet de l'application et de //
- // chaque DLL dans laquelle sont créés des threads. Aucune modification de //
- // code nécessaire. //
- // //
- // Principe de fonctionnement : Utilisation d'un FileMapping pour partager //
- // les pointeurs d'objets necessaires entre l'application et les DLL //
- // chargeant cette unité. Un objet est créé pour chaque DLL, et surcharge //
- // la variable globale de procedure WakeMainThread. Lorsqu'une //
- // synchronisation d'évènement est demandée dans une DLL, cet objet ajoute //
- // son pointeur dans une liste globale (protégée par une section critique), //
- // et active le thread de surveillance du module pricipal de l'application, //
- // qui synchronise un évènement dans lequel il propage la synchronisation //
- // a toutes les DLL qui l'ont demandé a travers les objets placés dans la //
- // liste globale. //
- // //
- // Change log : //
- // 10/03/2010 - SMA : Création //
- // //
- ////////////////////////////////////////////////////////////////////////////////
-
- unit DllThreadsSynchronize;
-
- interface
- implementation
-
- uses Forms, Classes, Windows, SyncObjs, SysUtils;
-
- Type
- TCheckSynchronizeFunc = function: Boolean;
-
- // Objet créé dans chaque DLL permettant de surcharger la variable de procedure globale
- // WakeMainThread et de redispatcher la méthode CheckSynchronize (Classes.pas)
- TSyncObj = Class
- private
- FLocalCheckSynchronize : TCheckSynchronizeFunc;
- public
- Procedure DLLWakeMainThread(Sender : TObject);
- Procedure DLLCheckSynchronize;
- Property LocalCheckSynchronize : TCheckSynchronizeFunc read FLocalCheckSynchronize write FLocalCheckSynchronize;
- end;
-
- // Thread de surveillance éxecuté dans le module principal (exe)
- // C'est lui qui redistribue la synchronisation depuis le thread
- // principal de l'application vers chaque DLL qui l'a demandé
- // via un synchronize()
- TSyncThread = Class(TThread)
- private
- Procedure DLLSynchronize;
- public
- procedure Execute; override;
- end;
-
- // Structure partagée entre tous les modules de l'application qui utilisent cette unité
- // via un FileMapping. Cette structure partage les pointeurs des objets communs
- // entre tous les modules.
- TSharedStruct = Packed record
- SyncList : TList; // Liste globale des TSyncObj necessitant une synchronisation
- DllSyncThread : TSyncThread; // Pointeur vers le thread de controle
- CriticalSection : TCriticalSection; // Pointeur vers la section critique protégeant la SyncList
- Signal : THandle; // Handle du signal (event) permettant de controler le thread de controle
- end;
-
- PSharedStruct = ^TSharedStruct;
-
- var DllThreadSyncObj : TSyncObj;
- DllSyncThread : TSyncThread;
- FSyncList : TList;
- FCriticalSection : TCriticalSection;
- FSignal : THandle;
- MappingHandle : THandle;
- SharedStruct : PSharedStruct;
- OldDllProc : TDLLProc;
-
- //****************************************************************************//
-
- { TSyncObj }
-
- // Objet créé dans chaque DLL permettant de surcharger la variable de procedure globale
- // WakeMainThread et de redispatcher la méthode CheckSynchronize (Classes.pas)
-
- procedure TSyncObj.DLLCheckSynchronize;
- begin
- // On appelle le CheckSynchronize de la DLL dans laquelle a été créé l'objet
- FLocalCheckSynchronize;
- end;
-
- procedure TSyncObj.DLLWakeMainThread(Sender : TObject);
- begin
- FCriticalSection.Enter; // Protection de la liste globale
- try
- try
- FSyncList.Add(Self); // Ajout de l'objet dans la liste globale : la DLL necessite une synchronisation
- finally
- SetEvent(FSignal); // Activation du thread de controle
- end;
- finally
- FCriticalSection.Leave;
- end;
- end;
-
- //****************************************************************************//
-
- { TSyncThread }
-
- // Thread de surveillance éxecuté dans le module principal (exe)
- // C'est lui qui redistribue la synchronisation depuis le thread
- // principal de l'application vers chaque DLL qui l'a demandé
- // via un synchronize()
-
-
- // Méthode synchronisée par le thread de controle
- procedure TSyncThread.DLLSynchronize;
- var FLocalSyncList : TList;
- begin
-
- // On utilise une liste locale pour pouvoir traiter
- // tranquillement les objets a traiter en dehors de la section
- // critique de protection de la liste globale,
- // car cette section critique peut provoquer des interbloquages
- // avec le ThreadLock de l'unité Classes.pas, qui est vérouillé pendant
- // le CheckSynchronize. Ainsi, le CheckSynchronize de chaque DLL est appelé
- // en dehors de notre section critique.
- FLocalSyncList := TList.Create;
-
- try
- FCriticalSection.Enter; // Protection de la liste globale
- try
- if FSyncList <> nil then
- begin
- // Transfert des éléments de la liste globale vers la liste locale
- while FSyncList.Count > 0 do
- begin
- FLocalSyncList.Add(FSyncList[0]);
- FSyncList.Delete(0);
- end;
- end;
- finally
- FCriticalSection.Leave;
- end;
-
- // Synchronisation des DLL en dehors de notre section critique :
- // pas de risques d'interblocages
- while FLocalSyncList.Count > 0 do
- begin
- TSyncObj(FLocalSyncList[0]).DLLCheckSynchronize; // Appel du CheckSynchronize de la DLL dans laquelle a été créé l'objet
- FLocalSyncList.Delete(0);
- end;
- finally
- FLocalSyncList.Free;
- end;
- end;
-
- // Boucle principale du thread de controle
- procedure TSyncThread.Execute;
- begin
- while not Terminated do
- begin
- WaitForSingleObject(FSignal, INFINITE); // Attente du signal demandant la synchronisation d'une DLL
- ResetEvent(FSignal);
- if Terminated then
- Exit;
-
- // Synchronisation d'une méthode locale dans laquelle la synchronisation
- // sera propagée aux DLL qui l'ont demandé
- Synchronize(DLLSynchronize);
- end;
- end;
-
- // Initialisation du module principal (exe)
- Procedure InitMainModule;
- var MappingName : String;
- begin
- MappingName := ExtractFileName(Application.Title) + '::' + IntToStr(GetCurrentProcessId);
-
- // Création d'un zone mémoire partagée pour l'échange des pointeurs d'objets communs avec les DLL
- MappingHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TSharedStruct), PChar(MappingName));
-
- if MappingHandle <> 0 then
- begin
- // Initialisation du pointeur de la structure partagée
- SharedStruct := MapViewOfFile(MappingHandle,
- FILE_MAP_ALL_ACCESS,
- 0,
- 0,
- SizeOf(TSharedStruct));
-
- // Création des objets partagés
- FSyncList := TList.Create;
- SharedStruct^.SyncList := FSyncList;
-
- DllSyncThread := TSyncThread.Create(True);
- SharedStruct^.DllSyncThread := DllSyncThread;
-
- FCriticalSection := TCriticalSection.Create;
- SharedStruct^.CriticalSection := FCriticalSection;
-
- FSignal := CreateEvent(nil, True, False, '');
- SharedStruct^.Signal := FSignal;
-
- // Initialisation du thread de controle
- ResetEvent(FSignal);
- DllSyncThread.Resume;
- end;
- end;
-
- // Initialisation d'une DLL
- Procedure InitLib;
- var MappingName : String;
- begin
- MappingName := ExtractFileName(Application.Title) + '::' + IntToStr(GetCurrentProcessId);
-
- // Ouverture d'un handle vers la zone de mémoire partagée (préalablement créée par le module principal)
- MappingHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TSharedStruct), PChar(MappingName));
-
- if MappingHandle <> 0 then
- begin
- // Initialisation du pointeur de la structure partagée
- SharedStruct := MapViewOfFile(MappingHandle,
- FILE_MAP_ALL_ACCESS,
- 0,
- 0,
- SizeOf(TSharedStruct));
-
- // Récupération des pointeurs d'objets partagés
- FSyncList := SharedStruct^.SyncList;
- DllSyncThread := SharedStruct^.DllSyncThread;
- FCriticalSection := SharedStruct^.CriticalSection;
- FSignal := SharedStruct^.Signal;
-
- // Création de l'objet de gestion de la synchronisation pour la DLL
- DllThreadSyncObj := TSyncObj.Create;
- WakeMainThread := DllThreadSyncObj.DLLWakeMainThread; // Surcharge de la variable globale de procédure WakeMainThread de la DLL
- DllThreadSyncObj.LocalCheckSynchronize := CheckSynchronize; // Mémorisation du pointeur de procedure CheckSynchronize de la DLL
- end;
- end;
-
- // Finalisation du module principal
- Procedure FinalizeMainModule;
- begin
- // Arret et libération du thread de controle
- SharedStruct^.DllSyncThread.FreeOnTerminate := True;
- SharedStruct^.DllSyncThread.Terminate;
- SetEvent(SharedStruct^.Signal);
-
- // Libération des objets partagés et fermeture des handles du signal et du FileMapping
- SharedStruct^.SyncList.Free;
- SharedStruct^.CriticalSection.Free;
- CloseHandle(SharedStruct^.Signal);
- UnmapViewOfFile(SharedStruct);
- CloseHandle(MappingHandle);
- end;
-
- // Finalisation d'une DLL
- Procedure FinalizeLib;
- begin
- // fermeture du partage du FileMapping
- UnmapViewOfFile(SharedStruct);
- // Libération de l'objet de synchronization de la DLL
- DllThreadSyncObj.Free;
- end;
-
- // Chargement de la DLL
- Procedure DLLEntryPoint(Reason: Integer);
- begin
- InitLib; // On effectue notre initialisation
- DllProc := OldDllProc; // puis on réaffecte la procédure de point d'entrée d'origine
- end;
-
- // Initialisation de l'unité
- initialization
- begin
- if IsLibrary then // Si c'est une DLL
- begin
- OldDllProc := DllProc; // On mémorise le point d'entrée de la DLL
- DllProc := @DLLEntryPoint; // puis on le remplace par notre propre point d'entrée
- end
- else
- InitMainModule; // Ce n'est pas une DLL, initialisation du module principal (exe)
- end;
-
- // Finalisation de l'unité
- finalization
- begin
- if IsLibrary then // Si c'est une DLL
- FinalizeLib // Finalisation de la DLL
- else
- FinalizeMainModule; // Sinon finalisation du module principal
- end;
-
- end.
////////////////////////////////////////////////////////////////////////////////
// Nom du fichier : DLLThreadSynchronize.pas //
// Auteur : S.Mazuir //
// Date : 10/03/2010 //
// Révision : 1 //
// Version : Delphi6 //
// Plateformes : Win32 //
// //
// Notes : //
// Unité permettant de gérér sans modification du code la synchronisation //
// des évènements générés par des threads créés dans une ou plusieurs DLL. //
// //
// Utilisation : Ajouter cette unité au projet de l'application et de //
// chaque DLL dans laquelle sont créés des threads. Aucune modification de //
// code nécessaire. //
// //
// Principe de fonctionnement : Utilisation d'un FileMapping pour partager //
// les pointeurs d'objets necessaires entre l'application et les DLL //
// chargeant cette unité. Un objet est créé pour chaque DLL, et surcharge //
// la variable globale de procedure WakeMainThread. Lorsqu'une //
// synchronisation d'évènement est demandée dans une DLL, cet objet ajoute //
// son pointeur dans une liste globale (protégée par une section critique), //
// et active le thread de surveillance du module pricipal de l'application, //
// qui synchronise un évènement dans lequel il propage la synchronisation //
// a toutes les DLL qui l'ont demandé a travers les objets placés dans la //
// liste globale. //
// //
// Change log : //
// 10/03/2010 - SMA : Création //
// //
////////////////////////////////////////////////////////////////////////////////
unit DllThreadsSynchronize;
interface
implementation
uses Forms, Classes, Windows, SyncObjs, SysUtils;
Type
TCheckSynchronizeFunc = function: Boolean;
// Objet créé dans chaque DLL permettant de surcharger la variable de procedure globale
// WakeMainThread et de redispatcher la méthode CheckSynchronize (Classes.pas)
TSyncObj = Class
private
FLocalCheckSynchronize : TCheckSynchronizeFunc;
public
Procedure DLLWakeMainThread(Sender : TObject);
Procedure DLLCheckSynchronize;
Property LocalCheckSynchronize : TCheckSynchronizeFunc read FLocalCheckSynchronize write FLocalCheckSynchronize;
end;
// Thread de surveillance éxecuté dans le module principal (exe)
// C'est lui qui redistribue la synchronisation depuis le thread
// principal de l'application vers chaque DLL qui l'a demandé
// via un synchronize()
TSyncThread = Class(TThread)
private
Procedure DLLSynchronize;
public
procedure Execute; override;
end;
// Structure partagée entre tous les modules de l'application qui utilisent cette unité
// via un FileMapping. Cette structure partage les pointeurs des objets communs
// entre tous les modules.
TSharedStruct = Packed record
SyncList : TList; // Liste globale des TSyncObj necessitant une synchronisation
DllSyncThread : TSyncThread; // Pointeur vers le thread de controle
CriticalSection : TCriticalSection; // Pointeur vers la section critique protégeant la SyncList
Signal : THandle; // Handle du signal (event) permettant de controler le thread de controle
end;
PSharedStruct = ^TSharedStruct;
var DllThreadSyncObj : TSyncObj;
DllSyncThread : TSyncThread;
FSyncList : TList;
FCriticalSection : TCriticalSection;
FSignal : THandle;
MappingHandle : THandle;
SharedStruct : PSharedStruct;
OldDllProc : TDLLProc;
//****************************************************************************//
{ TSyncObj }
// Objet créé dans chaque DLL permettant de surcharger la variable de procedure globale
// WakeMainThread et de redispatcher la méthode CheckSynchronize (Classes.pas)
procedure TSyncObj.DLLCheckSynchronize;
begin
// On appelle le CheckSynchronize de la DLL dans laquelle a été créé l'objet
FLocalCheckSynchronize;
end;
procedure TSyncObj.DLLWakeMainThread(Sender : TObject);
begin
FCriticalSection.Enter; // Protection de la liste globale
try
try
FSyncList.Add(Self); // Ajout de l'objet dans la liste globale : la DLL necessite une synchronisation
finally
SetEvent(FSignal); // Activation du thread de controle
end;
finally
FCriticalSection.Leave;
end;
end;
//****************************************************************************//
{ TSyncThread }
// Thread de surveillance éxecuté dans le module principal (exe)
// C'est lui qui redistribue la synchronisation depuis le thread
// principal de l'application vers chaque DLL qui l'a demandé
// via un synchronize()
// Méthode synchronisée par le thread de controle
procedure TSyncThread.DLLSynchronize;
var FLocalSyncList : TList;
begin
// On utilise une liste locale pour pouvoir traiter
// tranquillement les objets a traiter en dehors de la section
// critique de protection de la liste globale,
// car cette section critique peut provoquer des interbloquages
// avec le ThreadLock de l'unité Classes.pas, qui est vérouillé pendant
// le CheckSynchronize. Ainsi, le CheckSynchronize de chaque DLL est appelé
// en dehors de notre section critique.
FLocalSyncList := TList.Create;
try
FCriticalSection.Enter; // Protection de la liste globale
try
if FSyncList <> nil then
begin
// Transfert des éléments de la liste globale vers la liste locale
while FSyncList.Count > 0 do
begin
FLocalSyncList.Add(FSyncList[0]);
FSyncList.Delete(0);
end;
end;
finally
FCriticalSection.Leave;
end;
// Synchronisation des DLL en dehors de notre section critique :
// pas de risques d'interblocages
while FLocalSyncList.Count > 0 do
begin
TSyncObj(FLocalSyncList[0]).DLLCheckSynchronize; // Appel du CheckSynchronize de la DLL dans laquelle a été créé l'objet
FLocalSyncList.Delete(0);
end;
finally
FLocalSyncList.Free;
end;
end;
// Boucle principale du thread de controle
procedure TSyncThread.Execute;
begin
while not Terminated do
begin
WaitForSingleObject(FSignal, INFINITE); // Attente du signal demandant la synchronisation d'une DLL
ResetEvent(FSignal);
if Terminated then
Exit;
// Synchronisation d'une méthode locale dans laquelle la synchronisation
// sera propagée aux DLL qui l'ont demandé
Synchronize(DLLSynchronize);
end;
end;
// Initialisation du module principal (exe)
Procedure InitMainModule;
var MappingName : String;
begin
MappingName := ExtractFileName(Application.Title) + '::' + IntToStr(GetCurrentProcessId);
// Création d'un zone mémoire partagée pour l'échange des pointeurs d'objets communs avec les DLL
MappingHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TSharedStruct), PChar(MappingName));
if MappingHandle <> 0 then
begin
// Initialisation du pointeur de la structure partagée
SharedStruct := MapViewOfFile(MappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
SizeOf(TSharedStruct));
// Création des objets partagés
FSyncList := TList.Create;
SharedStruct^.SyncList := FSyncList;
DllSyncThread := TSyncThread.Create(True);
SharedStruct^.DllSyncThread := DllSyncThread;
FCriticalSection := TCriticalSection.Create;
SharedStruct^.CriticalSection := FCriticalSection;
FSignal := CreateEvent(nil, True, False, '');
SharedStruct^.Signal := FSignal;
// Initialisation du thread de controle
ResetEvent(FSignal);
DllSyncThread.Resume;
end;
end;
// Initialisation d'une DLL
Procedure InitLib;
var MappingName : String;
begin
MappingName := ExtractFileName(Application.Title) + '::' + IntToStr(GetCurrentProcessId);
// Ouverture d'un handle vers la zone de mémoire partagée (préalablement créée par le module principal)
MappingHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TSharedStruct), PChar(MappingName));
if MappingHandle <> 0 then
begin
// Initialisation du pointeur de la structure partagée
SharedStruct := MapViewOfFile(MappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
SizeOf(TSharedStruct));
// Récupération des pointeurs d'objets partagés
FSyncList := SharedStruct^.SyncList;
DllSyncThread := SharedStruct^.DllSyncThread;
FCriticalSection := SharedStruct^.CriticalSection;
FSignal := SharedStruct^.Signal;
// Création de l'objet de gestion de la synchronisation pour la DLL
DllThreadSyncObj := TSyncObj.Create;
WakeMainThread := DllThreadSyncObj.DLLWakeMainThread; // Surcharge de la variable globale de procédure WakeMainThread de la DLL
DllThreadSyncObj.LocalCheckSynchronize := CheckSynchronize; // Mémorisation du pointeur de procedure CheckSynchronize de la DLL
end;
end;
// Finalisation du module principal
Procedure FinalizeMainModule;
begin
// Arret et libération du thread de controle
SharedStruct^.DllSyncThread.FreeOnTerminate := True;
SharedStruct^.DllSyncThread.Terminate;
SetEvent(SharedStruct^.Signal);
// Libération des objets partagés et fermeture des handles du signal et du FileMapping
SharedStruct^.SyncList.Free;
SharedStruct^.CriticalSection.Free;
CloseHandle(SharedStruct^.Signal);
UnmapViewOfFile(SharedStruct);
CloseHandle(MappingHandle);
end;
// Finalisation d'une DLL
Procedure FinalizeLib;
begin
// fermeture du partage du FileMapping
UnmapViewOfFile(SharedStruct);
// Libération de l'objet de synchronization de la DLL
DllThreadSyncObj.Free;
end;
// Chargement de la DLL
Procedure DLLEntryPoint(Reason: Integer);
begin
InitLib; // On effectue notre initialisation
DllProc := OldDllProc; // puis on réaffecte la procédure de point d'entrée d'origine
end;
// Initialisation de l'unité
initialization
begin
if IsLibrary then // Si c'est une DLL
begin
OldDllProc := DllProc; // On mémorise le point d'entrée de la DLL
DllProc := @DLLEntryPoint; // puis on le remplace par notre propre point d'entrée
end
else
InitMainModule; // Ce n'est pas une DLL, initialisation du module principal (exe)
end;
// Finalisation de l'unité
finalization
begin
if IsLibrary then // Si c'est une DLL
FinalizeLib // Finalisation de la DLL
else
FinalizeMainModule; // Sinon finalisation du module principal
end;
end.
Conclusion
Pour l'utilisation, rien de plus simple : il suffit d'ajouter cette unité au projet de l'application, ainsi qu'a celui de chaque DLL necessitant des synchronisation d'évenements de threads.
Enjoy :)
Sources du même auteur
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
thread & dll -> Exception [ par WSTBoss ]
Bonjour à tous,j'ai une dll qui contient un thread, tout ce passe bien le thread marche comme il faut mais cependant lors du dechargement de la dll pa
evenement clavier [ par impossibleok ]
bjr; comment peut on savoir que la touche "Ctrl" est enfoncée? merci.
DLL Introuvable sous Win2000 mais ok sous XP. [ par atomicfe ]
Bonjour à tous,J'ai une application en Delphi 7 que j'ai faite , qui utilise une DLL toute simple que j'ai faite aussi en C.J'ai developpé l'applicati
expert dll [ par buguetj ]
Bonjour a tous, j'ai créé un lecteur de carte à puce...Je souhaiterais à présent créer un fichier dll (avec delphi expert) pour pouvoir intégrer ce ph
Modifier interface par une DLL [ par christophedlr ]
Bonsoir,Je voudrais savoir si il est possible via une DLL, de modifier l'interface du programme qui est dans l'EXE en lui même.Se serait pour un systè
mchid.dll [ par ldesmartin ]
bonjourJ'utilise la dll "mchid.dll" (avec delphi) qui permet d'utiliser l'interface USB d'un pc.Je recherche une description de chaque instruction de
Evenement au redimensionnement d'un composant graphique [ par orelien ]
Bonjour,J'ai créé un composant graphique héritant de la classe TWinControl sur lequel je souhaiterais ajouter des évènements lors de son redimensionne
Classe TThread dans composant, liaison entre deux instances ? [ par Bacterius ]
Bonjour ! Alors voilà un problème - j'essaye de faire un timer très précis : malheureusement celui-ci a besoin d'un thread pour fonctionner ! Je cherc
fonction glut pour evenement clavier [ par eole15 ]
Bonjour tout le monde...voila mon probleme je suis sous OpenGL (et j'utilse l'ami Glut3 2) et je fait un jeux video mais voila j'arrive a deplacer une
|
Derniers Blogs
[WP7] AJOUTER DES IMAGES DANS LA MEDIA LIBRARY D'UN WINDOWS PHONE 7[WP7] AJOUTER DES IMAGES DANS LA MEDIA LIBRARY D'UN WINDOWS PHONE 7 par Audrey
L'émulateur Windows Phone 7, fourni avec la version Beta des outils développeurs n'inclut aucune image dans sa bibliothèque. Pas très pratique de tester son application lorsque l'on souhaite que l'utilisateur puisse choisir une image présente dans le télé...
Cliquez pour lire la suite de l'article par Audrey VIVE LES MOCKS ET LES POCOSVIVE LES MOCKS ET LES POCOS par vLabz
J'observe régulièrement autour de moi de la confusion à propos de ces deux termes et j'aimerais juste rappeler ce qu'ils signifient. Je ne suis bien sûr pas le mieux placé pour faire une leçon mais je vais faire de mon mieux pour mettre en valeur ce q...
Cliquez pour lire la suite de l'article par vLabz [WF4] WORKFLOW AND CUSTOM ACTIVITIES - BEST PRACTICES (4/5)[WF4] WORKFLOW AND CUSTOM ACTIVITIES - BEST PRACTICES (4/5) par JeremyJeanson
Vendredi dernier Microsoft a publié le quatrième épisode des bonnes pratiques pour coder ses activités custom dans WF4 : endpoint.tv - Workflow and Custom Activities - Best Practices (Part 4) . Tout comme pour les précédents épisodes, j'ai pris le temps d...
Cliquez pour lire la suite de l'article par JeremyJeanson DéVELOPPEMENT MOBILE : .NET COMPACT FRAMEWORK & LIMITATIONSDéVELOPPEMENT MOBILE : .NET COMPACT FRAMEWORK & LIMITATIONS par Pi-R
Introduction :
Le développement d'applications mobiles est quelque peu différent du développement d'applications sous Windows. En effet, le développement d'applications mobiles se base sur le .NET Compact Fra...
Cliquez pour lire la suite de l'article par Pi-R IPHONE VERSUS WP7 CODINGIPHONE VERSUS WP7 CODING par Nicolas
Je relais une présentation sur slideshare.net, qui compare le développement sur Iphone et Windows Phone 7, qui ma fait sourire. I phone versus windows phone 7 coding View more presentations from www.donburnett.com. J'aurais bien aimé une comparai...
Cliquez pour lire la suite de l'article par Nicolas
Logiciels
Crystal Report (11)CRYSTAL REPORT (11)Crystal Reports est un outil de reporting souple et puissant, vous pouvez très facilement consult... Cliquez pour télécharger Crystal Report Academy System (12.0.2.0)ACADEMY SYSTEM (12.0.2.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Xilisoft iPod Vidéo Convertisseur 6 (6.0.3.0419)XILISOFT IPOD VIDéO CONVERTISSEUR 6 (6.0.3.0419)Xilisoft iPod Vidéo Convertisseur est un outil puissant de conversion d'iPod, facile à utiliser. ... Cliquez pour télécharger Xilisoft iPod Vidéo Convertisseur 6 Xilisoft iPhone Vidéo Convertisseur 6 (6.0.3.0419)XILISOFT IPHONE VIDéO CONVERTISSEUR 6 (6.0.3.0419)Xilisoft iPhone Vidéo Convertisseur est le meilleur logiciel de conversion iPhone qui peut facile... Cliquez pour télécharger Xilisoft iPhone Vidéo Convertisseur 6 Xilisoft iPad Vidéo Convertisseur 6 (6.0.3.0419)XILISOFT IPAD VIDéO CONVERTISSEUR 6 (6.0.3.0419)Il s'agit d'un logiciel polyvalent pour convertir les formats vidéo/audio populaires en formats p... Cliquez pour télécharger Xilisoft iPad Vidéo Convertisseur 6
|