完全な初心者のように聞こえるかもしれませんが、System.Timers.Timer に ISynchronizeInvoke を実装するにはどうすればよいですか?
mciSendString を呼び出すクラス (UI なし) があります。現在のステータスをポーリングするタイマーがあります。クラスからの呼び出しはすべて機能しますが、タイマー経過イベントからの呼び出しは機能しません。別のスレッドにあることを追跡しましたが、それ以上のことはありません。クラスと同じスレッドでデリゲートを呼び出す必要があると思いますが、まだ成功していません。
コードサンプル:
[DllImport("winmm.dll")]
private static extern Int32 mciSendString(string command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
public cPlayer()
{
tmrPoll = new System.Timers.Timer(1000);
tmrPoll.Enabled = false;
tmrPoll.Elapsed += new ElapsedEventHandler(tmrPoll_tick);
}
public void tmrPoll_tick(object source, ElapsedEventArgs e)
{
Poll();
}
private void Poll()
{
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
tmrPoll.Stop();
int res = 0;
res = mciSendString("status MediaFile position", _sbBuffer, _sbBuffer.Capacity, IntPtr.Zero);
if (res == 0) _position = int.Parse(_sbBuffer.ToString());
if (res == 0)
{
Console.WriteLine("Position = " + _sbBuffer.ToString());
} else {
Console.WriteLine("Failed: Error " + res.ToString());
}
res = mciSendString("status MediaFile length", _sbBuffer, _sbBuffer.Capacity, IntPtr.Zero);
if (res == 0) Console.WriteLine("Length = " + _sbBuffer.ToString());
if (res == 0) _length = int.Parse(_sbBuffer.ToString());
res = mciSendString("status MediaFile mode", _sbBuffer, _sbBuffer.Capacity, IntPtr.Zero);
if (res == 0) Console.WriteLine("Mode = " + _sbBuffer.ToString());
}
private void SendCommand(string cmd)
{
mciSendString(cmd, null, 0, IntPtr.Zero);
Poll();
}
明確にするために、SendCommand (それが何であれ、Play、Stop など) から呼び出すと、それは機能し、Poll() の結果は私が期待するものです。タイマーが起動すると、結果 (res) は 263 ですMCIERR_INVALID_DEVICE_NAME
。失敗した呼び出しのスレッド ID は、成功したものとは異なるため、ISynchronizeInvoke を使用する必要があると考えました。