L'objet est actuellement en cours d'utilisation ailleurs
J'obtiens cette erreur, et il semble que c'est parce que l'image même de l'objet est accessible par différents threads. Cependant, je suis en utilisant des verrous 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
}
}
}
Classe MySingleInstanceClass
aura qu'une seule instance. Les appels à MyImage
et Refresh()
peut venir de différents threads. Comme je le comprends, le code à l'intérieur lock(locker)
ne sera pas exécutée jusqu'à ce qu'il a fini dans un autre thread, mais j'ai toujours l'erreur. Quelqu'un peut-il point une faille dans le code?
Exception ressemble à ça:
Une exception de première chance de type 'System.InvalidOperationException' s'est produite dans System.Drawing.dll
Erreur: l'Objet est actuellement en usage ailleurs.
au Système.De dessin.Les graphiques.FromImage(Image)
à (les points de la ligne contenant var g = Graphiques.FromImage(myImage);)
- la serrure à l'intérieur de la getter/setter semble inutile....
- que pensez-vous de ce que vous atteindre avec verrouillage de la lecture (et le privé setter?) de MyImage? Je suis juste en pensant à haute voix pour ne présumez pas que j'ai la solution, mais ne serait-il pas plus de sens si le verrouillage de comportement dans la classe de consommateurs de cette classe?
- et bien, je vais faire en sorte qu'une thread qui appelle MyImage attend jusqu'à ce que le thread qui appelle Refresh() termine le bloc de code là, sinon je vais retourner myImage avant qu'il soit terminé le traitement. Pensez-vous que je n'en avez pas besoin? Pourquoi?
- Pouvez-vous afficher de message d'exception à l'intérieur de l'exception le cas échéant?
- C'est fondamentalement ce qui est en question le titre; j'ai ajouté au bas de la page.
Vous devez vous connecter pour publier un commentaire.
la
locker
objet n'est pas statique; ainsi, chaque nouvelle instance crée son propre casier; vous devez créerlocker
comme statique afin d'empêcher l'accès à partir d'autres threads si l'utilisation de plusieurs objets.Pour unique objet de scénario, l'utilisation d'un non statique de la classe de niveau variable comme un casier est bon. Si vous êtes employant ce scénario j'ai l'impression que la mise en œuvre de Singleton a quelques problèmes.
Mise à JOUR:
static
mot-clé de la déclaration desyncRoot
objet dans les deuxsingletion
etmulti-instance
scénario?Il n'a pas d'importance si l'objet est verrouillé est statique ou non. Le problème est que le
lock(locker)
à l'intérieur de la méthode de lecture déverrouille dès que l'image est renvoyée. Le retour de la référence à l'image n'est pas protégé par la serrure et peut être modifié dans le même temps comme un appel àRefresh
se produit.Une solution possible serait de se verrouiller sur le bitmap elle-même, mais qui peut introduire des blocages si pas fait avec soin.
return myImage
avecreturn (Bitmap)myImage.Clone()
vous permettra également d'éviter l'erreur. Mais sans voir le code qui utilise MySingleInstanceClass il est difficile de dire si ce serait une bonne solution.MySingleInstanceClass.Instance.Refresh()
. Thread 2 appelsMySingleInstanceClass.Instance.MyImage
, puis modifie le retour de l'image Bitmap. Ce sera la cause de l'exception que vous nous avez montré dans votre question.Dans mon application, la meilleure solution était:
Dans mon application il y a:
Copier quelques fichiers ajouter environ 0,01-0,2 sek. pour chaque demande, c'est mieux que statique de verrouillage sur l'app et l'utilisateur n'est pas neet attendre 10 min pour raport à générer (10 utilisateurs, cliquez sur le bouton générer au même moment).
vous pouvez cloner l'image avant de l'envoyer à la méthode