首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF UI冻结- UI线程冲突?

WPF UI冻结- UI线程冲突?
EN

Stack Overflow用户
提问于 2015-05-28 23:32:05
回答 1查看 2.7K关注 0票数 1

我正在尝试用WPF创建一个图像幻灯片效果。

用新图像更新幻灯片的方法在Windows.Forms.Timer中每隔几秒钟调用一次,并在Task中自己的线程中运行(如下面所示)。

代码语言:javascript
复制
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线程的两个任务线程之间的冲突?

这可能是什么原因?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-28 23:39:37

将工作放在另一个线程上的代码不会将工作放在另一个线程上。您的BeginInvoke将它发送回UI线程,您的所有工作都在那里完成。

在执行BeginInvoke调用之前做大量的工作,这样工作就会在后台线程上实际发生。

代码语言:javascript
复制
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,使其成为异步的,并且根本不使用线程。

代码语言:javascript
复制
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;
}
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30518760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档