3

我正在通过编写一个使用 iTunes COM API 的应用程序来学习 C# 事件处理。我有一个在 iTunes 停止播放歌曲时应该运行的方法,但是当我通过点击“停止/暂停”按钮触发应用程序中的事件时,该方法永远不会被调用。

编辑:根据 dboarman 的回复,我删除了 while 循环。现在该事件确实得到了处理,但前提是我在运行 PlayPlaylist() 之前重新启动了 iTunes。如果我第二次运行 PlayPlaylist(),则停止事件不再被触发/处理。

void trayIcon_Click(object sender, EventArgs e)
{
    PlayPlaylist();
}

public static void PlayPlaylist()
{

    itapp = new iTunesApp();
    itapp.OnPlayerStopEvent += 
        new _IiTunesEvents_OnPlayerStopEventEventHandler(itapp_OnPlayerStopEvent);

    lastPlaylist = itapp.LibraryPlaylist;

    itapp.Play();            
}

static void itapp_OnPlayerStopEvent(object iTrack)
{
    Debug.WriteLine("Stop Event fired");
    //...
}

在此处更新了 Pastebin 中的源代码(第 59-68 行是相关的)。

规格:我的应用程序应该从头到尾播放 Genius 推荐播放列表中的歌曲(iTunes 默认情况下不会连续播放 Genius 推荐)。StopEvent 应该触发列表中的下一首歌曲播放。

4

4 回答 4

2

这是有问题的完整代码:

public static void PlayPlaylist()
{
    itapp = new iTunesApp();
    itapp.OnPlayerStopEvent += new _IiTunesEvents_OnPlayerStopEventEventHandler(itapp_OnPlayerStopEvent);

    lastPlaylistID = itapp.LibraryPlaylist.playlistID;
    Debug.WriteLine("Last playlist:");
    Debug.WriteLine(lastPlaylistID);

    itapp.Play();

    while (true)
    {
        System.Threading.Thread.Sleep(1000);
    }
}

我怀疑while循环导致事件永远不会触发,因为线程会休眠一秒钟,因为true它,嗯......总是正确的。

我会将您的播放列表放入列表中。就像是:

static List<myTrack> Tracks;

public static void PlayPlaylist() 
{
    itapp = new iTunesApp();
    itapp.OnPlayerStopEvent += new _IiTunesEvents_OnPlayerStopEventEventHandler(itapp_OnPlayerStopEvent);

    foreach (myTrack track in Tracks)
    {
    // perform play
    }
}

看看它是如何为你工作的。

于 2010-02-12T05:20:09.473 回答
1

如果您希望线程阻塞并等待事件,您可以使用 ManualResetEvent 类。

private ManualResetEvent _resetEvent;

public void PlayPlaylist() 
{
    _resetEvent = new ManualResetEvent(false);
    itapp = new iTunesApp();
    itapp.OnPlayerStopEvent += new _IiTunesEvents_OnPlayerStopEventEventHandler(itapp_OnPlayerStopEvent);


    // Block until the resetEvent has been Set() or
    // give up waiting after 5 minutes
    _resetEvent.WaitOne(1000*5*60); 
}

在 itapp_OnPlayerStopEvent() 中,您必须调用: _resetEvent.Set();

为了回答你原来的问题,我很确定 while 循环没有给线程任何时间来响应停止事件,因此你没有看到它被处理。

于 2010-02-12T06:08:38.923 回答
1

我想知道事件处理程序没有取消挂钩的事实是否会导致某个问题(即 iTunes 持有对您的应用程序初始实例的单一引用)。这可以解决吗?我没有 iTunes API,所以我有点盲目;如果浪费时间,请道歉。

private bool stopIt;

private void trayIcon_Click(object sender, EventArgs e)
{
    if (!stopIt)
    {
        PlayPlaylist();
        stopIt = true;
    }
    else
    {
        StopPlaylist();
        stopIt = false;
    }
}

public static void PlayPlaylist()
{

    itapp = new iTunesApp();
    itapp.OnPlayerStopEvent += 
        new _IiTunesEvents_OnPlayerStopEventEventHandler(itapp_OnPlayerStopEvent);

    lastPlaylist = itapp.LibraryPlaylist;

    itapp.Play();            
}

public static void StopPlaylist()
{
    itapp.Stop(); // don't know if this is the right method name

    // unhook the event so the reference object can free if necessary.
    itapp.OnPlayerStopEvent -= 
        new _IiTunesEvents_OnPlayerStopEventEventHandler(itapp_OnPlayerStopEvent);
}

private static void itapp_OnPlayerStopEvent(object iTrack)
{
    Debug.WriteLine("Stop Event fired");
    // ...
}
于 2010-02-19T16:31:02.157 回答
1

当您的 itapp 超出范围时,请务必使用

System.Runtime.InteropServices.Marshal.ReleaseComObject(itapp);

或者您必须重新启动 iTunes 才能再次运行。使用 -= 取消注册事件处理程序可能也不会受到伤害。

于 2010-02-19T23:42:54.693 回答