Entwickler-Ecke
C# - Die Sprache - EventHandler innerhalb von lock aufrufen.
Kasko - Mi 19.06.19 01:21
Titel: EventHandler innerhalb von lock aufrufen.
Servus,
Erstmal der Code, dann die Fragen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83:
| using System; using System.Drawing; using System.IO; using System.Threading; using System.Threading.Tasks;
using AForge.Video.FFMPEG;
namespace VideoPlayer { public class Media { private object _sync = new object();
private CancellationTokenSource cts = null; private CancellationToken ct; private Task task = null;
private Bitmap _thumbnail; private MediaType _type; private string _uri;
public static int VideoThumbnailIndex = 15;
public event EventHandler<BitmapEventArgs> OnThumbnailChanged = null;
public Bitmap Thumbnail { get { lock (_sync) return _thumbnail; } set { lock (_sync) { _thumbnail = value; OnThumbnailChanged?.Invoke(this, new BitmapEventArgs(_thumbnail)); } } }
public MediaType Type { get; }
public string Uri { get => _uri; set { SetMediaType(value); _uri = value;
if (_type == MediaType.Video) StartReadingThumbnail(); } }
private void SetMediaType(string value) { if (!System.Uri.IsWellFormedUriString(value, UriKind.RelativeOrAbsolute)) throw new ArgumentException("Not well formated uri");
if (-1 != Array.IndexOf(new string[] { ".WAV", ".MID", ".MIDI", ".WMA", ".MP3", ".OGG", ".RMA" }, Path.GetExtension(value).ToUpper())) _type = MediaType.Audio; else if (-1 != Array.IndexOf(new string[] { ".AVI", ".MP4", ".DIVX", ".WMV" }, Path.GetExtension(value).ToUpper())) _type = MediaType.Video; else throw new NotSupportedException("Not supported file extension"); }
private void StartReadingThumbnail() { if (cts != null) { cts.Cancel(); task.Wait(); }
cts = new CancellationTokenSource(); ct = cts.Token;
task = Task.Factory.StartNew(() => { VideoFileReader reader = new VideoFileReader(); reader.Open(_uri);
for (int i = 1; i < VideoThumbnailIndex && !ct.IsCancellationRequested; i++) reader.ReadVideoFrame().Dispose();
Thumbnail = reader.ReadVideoFrame(); }, ct); } } } |
So zu meinen Fragen:
1. Ist der Zugriff auf die Thumbnail-Property sicher vor Multithreading-Exception?
2. Wird der EventHandler im Thread aufgerufen, in dem das Object der Klasse Media erstellt wurde oder im Task, der in der Methode StartReadingThumbnail erstellt wird?
Kasko - Mi 19.06.19 12:23
Okay dann zwei weitere Fragen:
1. Wie kann ich zusätzlich den Zugriff auf die Properties der Bitmap regeln?
2. Wie kann ich den EventHandler im "Erstellungsthread" des Objektes ausführen?
Chiyoko - Mi 19.06.19 13:05
Zu 1: (Eventuell) mit volatile als Schlüsselwort. Bin aber nicht 100% sicher, ob sich das auf die gesamte Klasse auswirkt.
Zu 2: z.b. mit SynchronizationContext
Ralf Jansen - Mi 19.06.19 13:21
Du hast eine Referenz auf dein Bitmap rausgegeben. Über das was ab jetzt über die Referenz passiert hast du (bzw. deine VideoPlayer Klasse) keinerlei Kontrolle mehr.
Die Lösung dazu hat @TH69 im ersten Beitrag gepostet. Kurzfassung gib eine Copy des Bitmaps raus. Diese Copy kann man dann beliebig ändern und über den Setter wieder zuweisen.
Das original Bitmap solltest du auch nicht über den OnThumbnailChanged Event rausgeben. Aus dem gleichen Grund.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!