C# 为什么它恨我?

C# 为什么它恨我?,c#,.net,winmm,C#,.net,Winmm,我刚开始玩弄C#/.NET/mono之类的东西,我正在尝试制作一个简单的歌曲播放器。为此,我使用了winmm.dll(没有找到简单的跨平台解决方案)。问题是:我需要在播放歌曲的同时更新轨迹栏。我有两个函数,Player.GetLength和Player.GetCurrentPosition,它们以毫秒为单位返回时间。如果我叫他们“正常”,一切都好。但我需要在计时器中调用它们,如下所示: new System.Threading.Timer((state) => { length =

我刚开始玩弄C#/.NET/mono之类的东西,我正在尝试制作一个简单的歌曲播放器。为此,我使用了
winmm.dll
(没有找到简单的跨平台解决方案)。问题是:我需要在播放歌曲的同时更新轨迹栏。我有两个函数,
Player.GetLength
Player.GetCurrentPosition
,它们以毫秒为单位返回时间。如果我叫他们“正常”,一切都好。但我需要在计时器中调用它们,如下所示:

new System.Threading.Timer((state) =>
{
    length = Player.GetLength();
    pos = Player.GetCurrentPosition();
    trackBar1.Value = (pos / length) * 100;
}, null, 0, 100);     
这是
GetLength
,与
GetCurrentPosition
类似:

public static int GetLength()
{
    StringBuilder s = new StringBuilder(128);
    mciSendString("status Song length", s, s.Capacity, IntPtr.Zero);
    return int.Parse(s.ToString());
}
问题:当调用这两个函数中的一个时,程序会停止,不会引发任何警告或异常。注意:我使用的是.NET


所以我想知道您是否可以向我解释一下我哪里弄错了:)

我要注意的一件事是System.Threading.Timer在它自己的线程中触发回调。由于您正在与UI交互,您可能希望使用System.Windows.Forms.Timer(作为窗体上的组件)或调用回UI,如下所示:

new System.Threading.Timer((state) =>
{
    length = Player.GetLength();
    pos = Player.GetCurrentPosition();
    trackBar1.Invoke(new Action(()=>trackBar1.Value = (pos / length) * 100));
}, null, 0, 100);   

同样,我不确定Player类是否支持/容忍多个线程,但如果不支持,则可能需要将整个回调调用到UI。

它可以工作,但我也想知道原因。你能给我解释一下到底发生了什么吗?在.NET中(以及在许多平台上的许多其他UI库中),UI控件的设计不允许从多个线程访问。这使他们能够更快地工作,因为他们不需要担心同步数据。在您的例子中,.NET实际上抛出了一个异常,抱怨您试图从后台线程访问UI,但因为它位于后台线程上,所以您看不到抛出的异常。因此我猜在使用线程时与它们交互的唯一方法是
。Invoke
,对吗?System.Threading.Timer类在线程池线程上运行回调,如下所述:这是正确的-您必须在与UI交互之前调用。