Je reçois cette erreur et il semble que c’est parce que le même object Bitmap est utilisé par différents threads. Cependant, j’utilise des serrures partout avec elle.
public class MySingleInstanceClass { private Object locker = new Object(); private Bitmap myImage = new Bitmap(100, 100); public Bitmap MyImage { get { lock (locker) return myImage; } private set { lock (locker) myImage = value; } } private void Refresh() { lock (locker) { var g = Graphics.FromImage(myImage); // do more processing } } }
La classe MySingleInstanceClass
n’aura qu’une seule instance. Les appels à MyImage
et Refresh()
peuvent provenir de différents threads. Autant que je sache, le code à l’intérieur du lock(locker)
ne sera pas exécuté tant qu’il n’aura pas fini dans un autre thread, mais j’obtiens toujours l’erreur. Quelqu’un peut-il signaler une faille dans le code?
L’exception ressemble à ça:
Une exception de première chance du type ‘System.InvalidOperationException’ s’est produite dans System.Drawing.dll
- Impossible de se connecter au serveur SSL utilisant uniquement des suites cryptographiques éphémères (il est impossible de contacter l’autorité de sécurité locale)
- NuGet – Les propriétés du fichier T4 sont différentes après l’installation
- Comment suivre les téléchargements avec ASP.NET?
- ASP.NET MVC HTML.AntiForgeryToken () avec plusieurs demandes AJAX à partir d’une page
- Quel est le meilleur moyen de détecter et de stocker le fuseau horaire dans lequel se trouve le client d’une application Web?
Erreur: L’object est actuellement utilisé ailleurs.
sur System.Drawing.Graphics.FromImage (Image image)
at (pointe vers la ligne contenant var g = Graphics.FromImage (myImage);)
l’object locker
n’est pas statique; ainsi chaque nouvelle instance crée son propre casier; vous devez créer un locker
statique afin d’empêcher l’access d’autres threads si vous utilisez plusieurs objects.
private static Object locker = new Object();
Pour un scénario d’object unique, l’utilisation d’une variable de niveau de classe non statique comme casier est appropriée. Si vous utilisez ce scénario, j’estime que la mise en oeuvre de Singleton pose quelques problèmes.
METTRE À JOUR:
public sealed class MySingleInstanceClass { private static volatile MySingleInstanceClass instance; private static object syncRoot = new Object(); private Bitmap myImage; private MySingleInstanceClass() { myImage = new Bitmap(100, 100); } public static MySingleInstanceClass Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new MySingleInstanceClass(); } } return instance; } } public Bitmap MyImage { get { lock (syncRoot) return myImage; } private set { lock (syncRoot) myImage = value; } } public void Refresh() { lock (syncRoot) { var g = Graphics.FromImage(myImage); // do more processing } } }
Peu importe que l’object verrouillé soit statique ou non. Le problème est que le lock(locker)
la méthode getter se déverrouille dès que le bitmap est renvoyé. La référence renvoyée au bitmap n’est pas protégée par le verrou et peut être modifiée en même temps qu’un appel à Refresh
.
Une solution possible serait de verrouiller le bitmap lui-même, mais cela peut créer des blocages s’il n’est pas fait avec soin.
Dans mon application, la meilleure solution était:
Dans mon application, il y a:
Copier quelques fichiers ajoute environ 0,01-0,2 sek. pour chaque demande, il est préférable que le locking statique de toutes les applications et les utilisateurs ne doivent pas attendre 10 minutes pour que raport soit généré (10 utilisateurs cliquent sur le bouton Générer au même moment).
private void DirectoryCopy(ssortingng sourceDirName, ssortingng destDirName, bool copySubDirs) { // Get the subdirectories for the specified directory. DirectoryInfo dir = new DirectoryInfo(sourceDirName); DirectoryInfo[] dirs = dir.GetDirectories(); if (!dir.Exists) { throw new DirectoryNotFoundException( "Source directory does not exist or could not be found: " + sourceDirName); } // If the destination directory doesn't exist, create it. if (!Directory.Exists(destDirName)) { Directory.CreateDirectory(destDirName); } // Get the files in the directory and copy them to the new location. FileInfo[] files = dir.GetFiles(); foreach (FileInfo file in files) { ssortingng temppath = Path.Combine(destDirName, file.Name); file.CopyTo(temppath, false); } // If copying subdirectories, copy them and their contents to new location. if (copySubDirs) { foreach (DirectoryInfo subdir in dirs) { ssortingng temppath = Path.Combine(destDirName, subdir.Name); DirectoryCopy(subdir.FullName, temppath, copySubDirs); } } } private void DeleteReportExecutionDirectory(ssortingng dirPath) { System.IO.DirectoryInfo downloadedMessageInfo = new DirectoryInfo(dirPath); foreach (FileInfo file in downloadedMessageInfo.GetFiles()) { file.Delete(); } foreach (DirectoryInfo dir in downloadedMessageInfo.GetDirectories()) { dir.Delete(true); } downloadedMessageInfo.Delete(); }
vous pouvez cloner cette image avant de l’envoyer à la méthode
Image newimg = (Image)img.Clone();