Open MediaPlayer - необработанное событие в теме
Я пытаюсь создать медиаплеер (с классом Media.MediaPlayer ()), и для этого я использую поток для обработки песен, которые загружаются пользователем с использованием OpenFileDialog. Я использую следующий код, чтобы начать процесс песни:
public static List<MediaFile> MediaList = new List<MediaFile>();
public static Queue<String> MediaFilesQueue = new Queue<String>();
public static void AddMediaFilesToMediaList()
{
String pathToFile;
while (MediaFilesQueue.Count > 0)
// all the files are loaded into the Queue before processing
{
pathToFile = MediaFilesQueue.Dequeue();
MediaData.MediaList.Add(new MediaFile(pathToFile));
MediaFileCreator mfCreator =
new MediaFileCreator(MediaData.MediaList.Count - 1);
mfCreator.CreateNewMediaFile();
}
}
И это класс MediaFileCreator:
public class MediaFileCreator
{
private int IndexOfMediaFileCurrentlyProcessed;
public MediaFileCreator(int idx)
{
IndexOfMediaFileCurrentlyProcessed = idx;
}
public void CreateNewMediaFile()
{
var indexOfMediaFileCurrentlyProcessed = IndexOfMediaFileCurrentlyProcessed;
var tempMediaFile = MediaData.MediaList[indexOfMediaFileCurrentlyProcessed];
var tempMediaPlayer = new MediaPlayer();
var waitHandle = new AutoResetEvent(false);
//EventHandler eventHandler = delegate(object sender, EventArgs args)
//{
// waitHandle.Set();
//};
tempMediaPlayer.MediaOpened += (sender, args) => waitHandle.Set();
tempMediaPlayer.Open(new Uri(tempMediaFile.PathToFile));
waitHandle.WaitOne();
//while (!tempMediaPlayer.NaturalDuration.HasTimeSpan)
//{
// Thread.Sleep(100);
//}
var tempTimeSpan = tempMediaPlayer.NaturalDuration.TimeSpan;
var hasVideo = tempMediaPlayer.HasVideo;
var hasAudio = tempMediaPlayer.HasAudio;
MediaData.MediaList[indexOfMediaFileCurrentlyProcessed].HasVideo = hasVideo;
MediaData.MediaList[indexOfMediaFileCurrentlyProcessed].HasAudio = hasAudio;
MediaData.MediaList[indexOfMediaFileCurrentlyProcessed].TimeSpanOfMediaFile
= tempTimeSpan;
}
И это класс MediaFile:
public class MediaFile
{
public bool HasAudio = false;
public bool HasVideo = false;
public TimeSpan TimeSpanOfMediaFile;
public String PathToFile = null;
public MediaFile(String pathToFile)
{
PathToFile = pathToFile;
}
}
Моя проблема в том, что программа останавливается наwaitHandle.WaitOne();
и пытается запустить эту линию снова и снова. Я попробовал другие варианты, такие как в первом разделе с комментариями, прикрепив этот обработчик события к событию Open, но результат был тот же:waitHandle.Set();
никогда не выполняется, и значение waitHandle всегда ложно. Единственный вариант, который мне удалось получить - это решение из второго комментария: блокировка потока (с Thread.Sleep) до полной загрузки файла (файл загружается, например, при инициализации TimeSpan) ... что потеря времени и снижение производительности для моего приложения. Проблема, очевидно, не в самом событии, потому что событие срабатывает, если оно запускается в главном потоке (метод AddMediaFilesToMediaList () вызывается из потока BackgroundWorker, который запускает метод внутри нового потока, когда обнаруживает, что в элементе есть элементы. Очередь; поток AddMediaFilesToMediaList () создается сnew Thread()
) и, очевидно, файл загружается, потому что TimeSpan инициализирован Я действительно хочу, чтобы приложение работало с использованием waitHandle или чего-то в этом роде. Я не хочу использовать Thread.Sleep (), потому что он уродлив, и у моего приложения также возникает утечка памяти, когда я пытаюсь загрузить много файлов (у меня занято более 1,2 ГБ памяти, и она останавливается с ошибками (OutOfMemory) - Я попытался загрузить в него 2048 песен), и я верю, что это может быть из-за Thread.Sleep (). Даже если это не так, отладку будет намного проще без проблем с Thread.Sleep ().
Так как я могу заставить waitHandle работать? Как я могу сделатьwaitHandle.Set();
бежать ? И если бы кто-нибудь имел представление о том, откуда это чрезмерное использование памяти, это было бы здорово! (Я лично считаю, что это вина Thread.Sleep (), но я не знаю, как от этого избавиться).
Редактировать: причина, по которой я использую объект MediaFileCreator, заключается в том, что изначально я хотел использовать пул потоков из 2-4 потоков для обработки файлов мультимедиа, но у меня возникла та же проблема, поэтому я удалил ThreadPool и попытался с помощью кода, опубликованного выше, но возникла та же проблема.
Изменить: мне удалось заставить его работать, используя второй поток для ожидания события (не самый чистый код сейчас, но я сделаю это правильно).
public class MediaFileCreator
{
private AutoResetEvent openedEvent = new AutoResetEvent(false);
public MediaFile CreateNewMediaFile(string filename)
{
var mFile = new MediaFile(filename);
var thread = new Thread(WaitForEvent);
const int maxTimeToWait = 2000;
openedEvent.Reset();
thread.Start(mFile);
var mediaPlayer = new MediaPlayer();
mediaPlayer.Open(new Uri(mFile.PathToFile));
openedEvent.WaitOne(maxTimeToWait);
var fromThread = Dispatcher.FromThread(Thread.CurrentThread);
if (fromThread != null) fromThread.InvokeShutdown();
return mFile;
}
private void WaitForEvent(object context)
{
var mFile = (MediaFile)context;
var mediaPlayer = new MediaPlayer();
mediaPlayer.MediaOpened +=
delegate
{
if (mediaPlayer.NaturalDuration.HasTimeSpan)
mFile.TimeSpanOfMediaFile = mediaPlayer.NaturalDuration.TimeSpan;
mFile.HasAudio = mediaPlayer.HasAudio;
mFile.HasVideo = mediaPlayer.HasVideo;
mFile.Success = true;
mediaPlayer.Close();
openedEvent.Set();
};
mediaPlayer.MediaFailed +=
delegate
{
mFile.Failure = true;
mediaPlayer.Close();
openedEvent.Set();
};
mediaPlayer.Open(new Uri(mFile.PathToFile));
Dispatcher.Run();
}
}