cs_LaNono
Messages postés37Date d'inscriptionmardi 30 septembre 2008StatutMembreDernière intervention26 avril 2011
-
5 déc. 2008 à 11:57
cs_LaNono
Messages postés37Date d'inscriptionmardi 30 septembre 2008StatutMembreDernière intervention26 avril 2011
-
5 déc. 2008 à 16:30
Bonjour à tous,
J'ai un programme qui effectue une traitement en boucle et durant ce traitement, il peut faire des opérations comme :
- Dessiner sur un composant graphics et sauvegarder ce fichier sur le disque
- Créer une capture d'écran
Si je n'utilise pas de multitâche, le traitement se passe très bien, les images sont créées et sauvées.
Comme le traitement dur un certain temps, j'ai insérer ce traitement dans un multithread à l'aide du composant BackgroundWorker. qui me permet d'avoir un bouton "Annuler" en cours du traitement
Mon problème est que depuis que j'utilise ce composant, des exceptions sont levées lorsque j'utilise l'instruction Save d'un objet bitmap et que la lecture de données dans le presse papier (Au moment de la capture d'écran) me retourne une valeur nulle.
Quelqu'un connait-il la raison de cette erreur? peut-on accéder à l'OS (Système de fichier, clipboard) depuis une application multithread?
Apparemment, mon problème vient du fait que BackgroundWorker travaille avec des threads en mode MTA alors qu'ils doivent être en mode STA pour accéder au clipboard.
j'ai pas tout compris mais tout fonctionne maintenant ;-)
Le newbie
Messages postés200Date d'inscriptionmardi 17 octobre 2006StatutMembreDernière intervention24 mars 20122 5 déc. 2008 à 12:15
Salut,
Si tu pouvais nous donner les exception qui sont levées on pourrait plus t'aider.
Ensuite, est ce que tu fais ton le traitement de capture dans le background worker c'est à dire prise de l'image et enregistrement du fichier. Ou est ce que tu fais la capture dans le background et la sauvegarde dans ton thread principal.
Il me semble que tu dois tout faire dans le background worker puisque les seuls échanges possibles entre tes threads sont des entiers qui te permettent de connaître l'état d'avancmeent de ton thread dérivé. Cela expliquerait peut être pourquoi ta capture est NULL.
cs_LaNono
Messages postés37Date d'inscriptionmardi 30 septembre 2008StatutMembreDernière intervention26 avril 20111 5 déc. 2008 à 13:35
Hello,
merci de ta réponse!
J'effectue l'entier du traitement des images dans le BackgroundWorker
l'exception levée lorsque j'utilise l'expression :
MonBitmap.Save(FileName, Imaging.ImageFormat.Bmp)
est la suivante :
L'exception System.Runtime.InteropServices.ExternalException n'a pas été gérée par le code utilisateur
ErrorCode=-2147467259
Message="Une erreur générique s'est produite dans GDI+."
Source="System.Drawing"
StackTrace:
à System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
à System.Drawing.Image.Save(String filename, ImageFormat format)
à DocumentationGOelan.DGToolImageManager.DGToolImageManager_DrawTool(String FileName, DGImageGOelan Image) dans D:\work\petignat_tp_goelan_trunk\Application\DocumentationGOelan\DocumentationGOelan\DGToolImageManager.vb:ligne 572
à DocumentationGOelan.DGGOelanManager.DGGOelanManager_SetGOelanGammeValues(List`1& Controls, List`1& GOelanImages, DGPaper& Paper, List`1& ReturnedDataList, List`1& ReturnedImageList, Int32 ProgressMaxValue, Int32& ProgressCurrentValue, BackgroundWorker& Worker, DoWorkEventArgs& WorkerEvent) dans D:\work\petignat_tp_goelan_trunk\Application\DocumentationGOelan\DocumentationGOelan\DGGOelanManager.vb:ligne 810
à DocumentationGOelan.DGGenerationFrm.DGGenerationFrm_ReadGOelanData(BackgroundWorker ReadWorker, DoWorkEventArgs WorkerEvent) dans D:\work\petignat_tp_goelan_trunk\Application\DocumentationGOelan\DocumentationGOelan\DGGenerationFrm.vb:ligne 150
à DocumentationGOelan.DGGenerationFrm.bgwBackground_DoWork(Object sender, DoWorkEventArgs WorkerEvent) dans D:\work\petignat_tp_goelan_trunk\Application\DocumentationGOelan\DocumentationGOelan\DGGenerationFrm.vb:ligne 183
à System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
à System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
Concernant le clipboard, je l'utilise de la manière suivante :
Lorsque je suis dans le BackgroundWorker, data est à nothing alors qu'il contient l'image prise par la capture d'écran si je n'utilise pas de background worker
J'avoue que je suis un peu paumée (Disons que ces histoires de multitâche n'ont jamais vraiment été claires pour moi ;-) )
Personnelement, comme tu peux le voir, je ne pense en aucun cas que cela puisse venir du BGW. Je pense que c'est un pb de code. Cependant tu as l'air de dire que cela marche.
PS : hésite pas à mettre un petit peu plus de code histoire qu'on comprènnent bien. Voir tes déclarations, des procédures complètes et si tu as des données confidentielles, tu les rempace par des XXXXXX par exemple mais n'hésite pas à en mettre plus.
Vous n’avez pas trouvé la réponse que vous recherchez ?
cs_LaNono
Messages postés37Date d'inscriptionmardi 30 septembre 2008StatutMembreDernière intervention26 avril 20111 5 déc. 2008 à 15:41
Re!
En fait, je crois que je me suis mal exprimée, je vais suivre ton conseil et mettre plus de code ;-)
Les deux erreurs que j'ai décrites se passent à deux endroits et pour deux tâches complètement différentes
Première erreur : Bitmap.save
------------------------------
Je viens de résoudre cette erreur :
En fait, comme j'ajoute la gestion avec le BackgroundWorker petit à petit, j'ai commenter toute la suite de mon code qui me prenait beaucoup de temps
Du coup, juste après que j'enregistre le bitmap, je n'ai plus rien à faire et je me retrouve à la fin de la fonction qui lance mon thread.
Le problème c'est qu'à la fin de cette fonction, une ligne de code supprime ces images, car elles sont temporaires
Ce qui s'est passé, c'est que les images étaient supprimées alors que leur enregistrement n'était même pas terminé. d'où l'erreur.
Deuxième erreur : Réalisation d'une capture d'écran
---------------------------------------------------
Le problème n'est pas de mettre mon code, mais c'est qu'il y a tellement de traitement pour arriver à la capture que c'est difficile à expliquer ;-)
J'ai donc reproduit l'erreur pour la capture d'écran par un petit exemple que voici :
' .: Forme principale du projet :.
' Cette forme contient deux boutons :
' 1 pour faire une capture sans BackgroundWorker
' 1 pour faire une capture dans un BackgroundWorker
Imports System.ComponentModel
Public Class Form1
'Capture d'écran sans BackgroundWorker
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
DGSnapshotGOelanManager_MakeBitmapFromScreenShot(Application.StartupPath + "/TMP/TMP.bmp")
End Sub
'Capture d'écran avec le backgroundWorker
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.bgw.RunWorkerAsync()
End Sub
Private Sub bgw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
Dim worker As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker)
DGSnapshotGOelanManager_MakeBitmapFromScreenShot(Application.StartupPath + "/TMP/TMPbgw.bmp")
' .:Module de gestion des captures d'écran :.
Imports System.Drawing
Imports System.Drawing.Imaging
Module DGSnapshotGOelanManager
'Procédure de l'API Windows keybd_event permettant de simluer une touche pressée au clavier
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
Private Function DGSnapshotGOelanManager_SaveScreen(ByVal FileName As String) As Boolean
Dim data As IDataObject
Dim bmap As Bitmap
Dim FramedBitmap As Bitmap
Dim Text As String = ""
Dim ImageGraphics As Graphics
'Récupération de l'image enregistrée dans le presse papier par la capture d'écran
data = Clipboard.GetDataObject()
'Enregistrement de cette image au format BMP
If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
'Conversion de l'image au format bitmap
bmap = CType(data.GetData(GetType(System.Drawing.Bitmap)), Bitmap)
'recadrage de l'image
FramedBitmap = New Bitmap(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height)
ImageGraphics = Graphics.FromImage(FramedBitmap)
ImageGraphics.DrawImage(bmap, New PointF(0, 0))
'Enregistrement de l'image au format Bitmap
FramedBitmap.Save(FileName, Imaging.ImageFormat.Bmp)
ImageGraphics.Dispose()
End If
End Function
Public Sub DGSnapshotGOelanManager_MakeBitmapFromScreenShot(ByVal FileName As String)
'Copie d'écran
Call keybd_event(System.Windows.Forms.Keys.PrintScreen, 0, 0, 0)
'attente que l'image soit finie de copier
System.Windows.Forms.Application.DoEvents()
DGSnapshotGOelanManager_SaveScreen(FileName)
End Sub
La solution sans BackgroundWorker (Bouton1) fonctionne très bien
Pour la solution dans le BackgroundWorker(Bouton2), l'instruction Clipboard.GetDataObject() retourne Nothing
Je ne comprend pas très bien ce qui peut se passer