如果你的要求是:
- 開始按鈕,播放聲音,然後開始顯示在屏幕上經過時間的計時器。
- 停止按鈕停止任何當前的計時器,讓屏幕上的最後一個值。
- 在Windows窗體中實現。
以下代碼是如何獲得上述要求的基本示例。它利用SoundPlayer的PlaySync方法,BackgroundWorker(將標籤上的值更新爲流逝的秒數)以及用於實際記錄流逝時間的秒錶。絕對不是實現這一目標的最佳方式,但它應該爲您提供一個起點。
要注意的重要一點是,你不能從一個線程是從創建標籤(通常是UI線程)的線程不同更新標籤。所以,如果你想從另一個線程更新標籤的文本,你需要使用標籤.Invoke方法(見下面的代碼的ThreadSafeUpdateLabel方法)。
此代碼沒有考慮到某些垃圾郵件點擊「開始」按鈕的情況(它只是單擊播放聲音的次數),並且只要您點擊「開始」按鈕,UI就會凍結聲音發揮。我將留下解決這些問題給你作爲代碼的自然延伸。
反正到代碼:
private Stopwatch _timer = new Stopwatch();
private BackgroundWorker _worker;
private void btnStop_Click(object sender, EventArgs e)
{
CancelExistingBackgroundWorker();
_timer.Stop();
}
private void btnStart_Click(object sender, EventArgs e)
{
CancelExistingBackgroundWorker();
_timer.Reset();
UpdateLabel(0);
_worker = new BackgroundWorker() { WorkerSupportsCancellation = true };
_worker.DoWork += (a, b) =>
{
while (true)
{
if ((a as BackgroundWorker).CancellationPending) return;
ThreadSafeUpdateLabel();
Thread.Sleep(100);
}
};
var soundPlayer = new SoundPlayer("wavfile.wav");
soundPlayer.PlaySync();
_timer.Start();
_worker.RunWorkerAsync();
}
private void ThreadSafeUpdateLabel()
{
if (lblElapsed.InvokeRequired)
{
lblElapsed.Invoke(new Action(() => ThreadSafeUpdateLabel()));
}
else
{
UpdateLabel(_timer.Elapsed.TotalSeconds);
}
}
private void UpdateLabel(double seconds)
{
lblElapsed.Text = seconds.ToString();
}
private void CancelExistingBackgroundWorker()
{
if (_worker != null)
{
_worker.CancelAsync();
_worker.Dispose();
}
}
好吧,但你有什麼問題嗎? –
我忘了告訴計時器不想開始。有什麼建議麼??? – user3029389
你怎麼知道的'Stopwatch'還沒有開始?是'sw.IsRunning = FALSE'和'sw.Elapsed = TimeSpan.Zero'? –