我创建了一个声音播放器,可以在任何给定的时间播放一组声音中的特定声音。集合中的某个声音需要以循环方式播放。以下是我的代码:
public class SoundService : ISoundService
{
private Dictionary<string, SoundPlayer> SoundCollections { get; set; }
private SoundPlayer _soundPlayerPlaceHolder;
private readonly CancellationTokenSource _cancellationToken = new CancellationTokenSource();
private CancellationToken _token;
public void Play(SoundType soundType)
{
_token = _cancellationToken.Token;
Task.Factory.StartNew(() => PlaySound(soundType), _token);
}
private void PlayLooping(SoundType soundType)
{
if (!SoundCollections.ContainsKey(soundType.ToString()))
{
s_Log.Error("Error retrieving sound from Sound collection. XXX.SoundService");
return;
}
_soundPlayerPlaceHolder = SoundCollections[soundType.ToString()];
if (_token.IsCancellationRequested)
{
if (_soundPlayerPlaceHolder != null)
{
_soundPlayerPlaceHolder.Stop();
_soundPlayerPlaceHolder = null;
}
return;
}
_soundPlayerPlaceHolder.PlayLooping();
}
public void StopSound()
{
_cancellationToken.Cancel();
}
public void LoadSounds()
{
var sounds = Enum.GetValues(typeof (SoundType));
SoundCollections = new Dictionary<string,SoundPlayer>();
foreach (var soundType in sounds)
{
var resourceName = GetResourceNameAttribute(soundType);
if (string.IsNullOrEmpty(resourceName))
continue;
try
{
var stream = Resources.ResourceManager.GetStream(resourceName);
var soundPlayer = new SoundPlayer(stream);
soundPlayer.LoadAsync();
SoundCollections.Add(soundType.ToString(), soundPlayer);
s_Log.Info(string.Format(@"loading sound {0}", soundType));
}
catch (Exception e)
{
s_Log.Error(e);
}
}
}
private string GetResourceNameAttribute(object enumToQuery)
{
var fi = enumToQuery.GetType().GetField(enumToQuery.ToString());
var attributes = (ResourceNameAttribute[])fi.GetCustomAttributes(
typeof(ResourceNameAttribute), false);
return attributes.Length > 0 ? attributes[0].ResourceName : enumToQuery.ToString();
}
/// <summary>
/// .
/// </summary>
/// <param name="aSoundType"></param>
private void PlaySound(SoundType aSoundType)
{
s_Log.Info("loading sound {0}", aSoundType.ToString());
if (aSoundType == SoundType.ItemNotFound)
{
PlayLooping(aSoundType);
}
else
{
if (_soundPlayerPlaceHolder == null)
SoundCollections[aSoundType.ToString()].Play();
}
}
}
我遇到的问题是,在一个声音播放器在循环中播放(它正在工作),并且取消令牌被取消后,我无法再在循环中演奏相同的声音。我不知道为什么会出现这种情况,我已经尝试了许多其他线程选项(Task、BackgroundWorker),但我运气不佳。单曲播放效果很好,只是回放循环不起作用。没有例外,日志中没有任何内容。。。。我迷路了。。。想法?
这样的一个角落。。。。每次调用该方法时,取消令牌都是相同的。所以,当我在任务没有启动之前取消它时。。。。Derp。