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スレッドが 1 秒間スリープするため、ループが原因でイベントが発生しないのではないかと考えてい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

I'm wondering if the fact that the event handler doesn't unhook is causing an issue somewhere along the line (i.e. iTunes holds a singular reference to the initial instance of your app). This may solve it? I don't have the iTunes API so I'm flying a little blind; apologize if it's a waste of time.

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 に答える
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() 内で次を呼び出す必要があります。

元の質問に答えるために、while ループが停止イベントに応答する時間をスレッドに与えていないことは確かです。したがって、処理されていることがわかりません。

于 2010-02-12T06:08:38.923 に答える