簡體   English   中英

WPF UI凍結-UI線程沖突?

[英]WPF UI Freezes - UI Thread conflict?

我正在嘗試使用WPF創建圖像幻燈片效果。
Windows.Forms.Timer每隔幾秒鍾調用一次用新圖像更新幻燈片的方法,該方法在Task的自己線程中運行(如下所示)。

private void LoadImage()
    {
        Task t = Task.Run(() =>
        {    
           this.Dispatcher.BeginInvoke((Action)(() =>
           {
               TimeSpan delay = new TimeSpan(0, 0, 0, 0, 0);
               Fader.ChangeSource(image, BitmapFromUri(new Uri(compPath + oComps[nCount].name)), delay, delay);
               image.Visibility = System.Windows.Visibility.Visible;

               mediaElement.Stop();
               mediaElement.Close(); ;
               mediaElement2.Stop();
               mediaElement2.Close();
               mediaElement.Visibility = System.Windows.Visibility.Collapsed;
               mediaElement2.Visibility = System.Windows.Visibility.Collapsed;

               imageLoop.Interval = oComps[nCount].duration;

               nCount++;

               imageLoop.Start();
           }));
        });
    }

同時,覆蓋中的畫布底部會出現一個滾動文本橫幅。 這也正在其自己的線程中運行,通過Dispatcher更新UI。

每幾張圖像,包括滾動文本幻燈片,都會暫停一兩秒鍾,似乎在等待圖像加載。 此行為是意外的,因為每個元素都在單獨的線程中。


這可能是兩個更新UI線程的Task線程之間的沖突嗎?
是什么原因造成的?

您將代碼放在另一個線程上的代碼不會將工作放在另一個線程上。 您的BeginInvoke會將其發送回UI線程,並且所有工作都在此完成。

在執行BeginInvoke調用之前,請先進行繁重的工作,這樣工作實際上就在后台線程上進行。

private void LoadImage()
{
    Task t = Task.Run(() =>
    {    
       //I assume BitmapFromUri is the slow step.
       var bitmap = BitmapFromUri(new Uri(compPath + oComps[nCount].name);

       //Now that we have our bitmap, now go to the main thread.
       this.Dispatcher.BeginInvoke((Action)(() =>
       {
           TimeSpan delay = new TimeSpan(0, 0, 0, 0, 0);

           //I assume Fader is a control and must be on the UI thread, if not then move that out of the BeginInvoke too.
           Fader.ChangeSource(image, bitmap), delay, delay);
           image.Visibility = System.Windows.Visibility.Visible;

           mediaElement.Stop();
           mediaElement.Close(); ;
           mediaElement2.Stop();
           mediaElement2.Close();
           mediaElement.Visibility = System.Windows.Visibility.Collapsed;
           mediaElement2.Visibility = System.Windows.Visibility.Collapsed;

           imageLoop.Interval = oComps[nCount].duration;

           nCount++;

           imageLoop.Start();
       }));
    });

我懷疑您的橫幅也實際上不在其他線程上工作,您可能需要查看一下。


如果可能的話,更好的解決辦法是將BitmapFromUri重寫為異步的,而不使用線程。

private async Task LoadImageAsync()
{
   TimeSpan delay = new TimeSpan(0, 0, 0, 0, 0);      

   var bitmap = await BitmapFromUriAsync(new Uri(compPath + oComps[nCount].name);
   Fader.ChangeSource(image, bitmap), delay, delay);
   image.Visibility = System.Windows.Visibility.Visible;

   mediaElement.Stop();
   mediaElement.Close(); ;
   mediaElement2.Stop();
   mediaElement2.Close();
   mediaElement.Visibility = System.Windows.Visibility.Collapsed;
}

暫無
暫無

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

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