簡體   English   中英

線程睡眠在 Windows Phone 7 上運行不佳

[英]Thread sleep doesn't work well on Windows Phone 7

我想讓我的程序休眠幾秒鍾。 當我使用thread.sleep(x)整個程序沒有響應。 根據這篇文章 -> http://msdn.microsoft.com/en-us/library/hh184840(v=VS.92).aspx不負責 3 秒的應用程序沒有通過認證:/(我必須等待 5 秒)。

不要讓應用程序的主線程休眠。 相反,做任何需要在應用程序的后台線程中等待的事情。

如您所見,如果您在應用程序的主線程中調用 Thread.Sleep() ,應用程序將對幕后的 UI 消息循環無響應。 這是因為您在處理一條消息(觸發等待的 UI 事件)時阻止了執行,因此無法處理應用程序的其他消息。

相反,構造此代碼以異步運行。 我猜有一些方法可以包含大部分繁重的工作,包括睡眠。 只要這不是事件處理程序(如果是,請重構它),您就可以設置第二個線程來運行此方法,並添加該方法在完成時將調用的“回調”方法,這將使用結果。 這需要更多的工作,但它可以保持應用程序的響應性,並且通常是一種很好的做法,尤其是在多核設備上(現在甚至手機都使用雙核 CPU)。 有很多方法可以設置多線程操作。 Delegate.BeginInvoke 是我最喜歡的:

public delegate void BackgroundMethod()

public void HandleUITrigger(object sender, EventArgs e)
{
   //we'll assume the user does something to trigger this wait.

   //set up a BackgroundMethod delegate to do our time-intensive task
   BackgroundMethod method = DoHeavyLifting;

   //The Delegate.BeginInvoke method schedules the delegate to run on 
   //a thread from the CLR's ThreadPool, and handles the callback.
   method.BeginInvoke(HeavyLiftingFinished, null);

   //The previous method doesn't block the thread; the main thread will move on
   //to the next message from the OS, keeping the app responsive.
}

public void DoHeavyLifting()
{
   //Do something incredibly time-intensive
   Thread.Sleep(5000);

   //Notice we don't have to know that we're being run in another thread,
   //EXCEPT this method cannot update the UI directly; to update the UI
   //we must call Control.Invoke() or call a method that Invokes itself
   ThreadSafeUIUpdate();
}

public void ThreadSafeUIUpdate()
{
   //A simple, thread-safe way to make sure that "cross-threading" the UI
   //does not occur. The method re-invokes itself on the main thread if necessary
   if(InvokeRequired)
   {
      this.Invoke((MethodInvoker)ThreadSafeUIUpdate);
      return;
   }

   //Do all your UI updating here.
}

public void HeavyLiftingFinished()
{
   //This method is called on the main thread when the thread that ran 
   //DoHeavyLifting is finished. You can call EndInvoke here to get
   //any return values, and/or clean up afterward.
}

您需要重新考慮暫停時要嘗試做什么。 鑒於我們沒有太多關於您嘗試通過此暫停實現的目標的信息,這有點難說,但我將在這里舉一個例子來說明如何在無需暫停整個應用程序的情況下獲得想要的效果(這是你永遠不應該做的)。

假設你想下載文件 A,然后等待 5 秒,然后下載文件 B。你可以通過運行這樣的東西來做到這一點:

var file = downloadFileA();
new Thread((ThreadStart)delegate
{
    Thread.Sleep(5000);
    downloadFileB();
});

此外,最好使實際的下載調用異步(如果它正在下載您正在執行),只是為了確保您不會影響 GUI。

或者,您可以像這樣在后台線程中進行下載:

new Thread((ThreadStart)delegate
{
    var file = downloadFileA();
    Thread.Sleep(5000);
    downloadFileB();
});

免責聲明:任何地方的Thread.Sleep(n)幾乎都是“代碼異味”,這意味着它表明應用程序中的其他代碼也將成為問題。 我一般完全避免使用它(我從未遇到過必須使用Thread.Sleep的場景)。

但是,在您的情況下, Thread.Sleep(5000)的簡單替代品可能就是這樣做:

for (int i = 0; i < 10; i++) {
    Thread.Sleep(500);
}

您將獲得 5 秒的總體等待時間,但 UI 的鎖定時間永遠不會超過半秒。

看起來像是 ThreadPool.QueueUserWorkItem 的工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM