首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尽管进程在单独的线程中运行,但WPF UI没有响应。为什么?

尽管进程在单独的线程中运行,但WPF UI没有响应。为什么?
EN

Stack Overflow用户
提问于 2010-01-01 17:26:35
回答 3查看 1.1K关注 0票数 0

在WPF中使用线程对我没有什么影响。UI仍然没有响应。

这是我的密码:

代码语言:javascript
复制
private void button1_Click_1(object sender, RoutedEventArgs e)
{
    Thread th = new Thread(new ThreadStart(LoadImages));
    th.Start();
}

void LoadImages()
{
    this.Dispatcher.Invoke(DispatcherPriority.Normal, new System.Windows.Forms.MethodInvoker(delegate() {
        IService1 svc = ConnectAndGetObject();
        foreach (byte[] imgbytes in svc.GetImageDateWise(datePicker1.DisplayDate, DateTime.Now, "test"))
        {
            using (MemoryStream mem = new MemoryStream(imgbytes))
            {
                BitmapImage jpgimage = new BitmapImage();
                jpgimage.BeginInit();

                jpgimage.CacheOption = BitmapCacheOption.OnLoad;

                jpgimage.StreamSource = mem;

                jpgimage.EndInit();

                //  PngBitmapDecoder decodejpg = new PngBitmapDecoder(mem, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnDemand);
                Image wpfimage = new Image();
                wpfimage.Source = jpgimage.Clone();

                lbx.Items.Add(wpfimage);
                lbx.UpdateLayout();
                Thread.Sleep(1000);
            }
        }
    }));
}

更新工作代码:

代码语言:javascript
复制
      List<MemoryStream> mems = new List<MemoryStream>();
        void LoadImages()
        {

            IService1 svc = ConnectAndGetObject();
            foreach (byte[] imgbytes in svc.GetImageDateWise(GetDate(), DateTime.Now, "test"))
            {
   this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate() {
       mems.Add(new MemoryStream(imgbytes));


                    BitmapImage jpgimage = new BitmapImage();
                    jpgimage.BeginInit();

                    jpgimage.CacheOption = BitmapCacheOption.None;

                    jpgimage.StreamSource = mems[mems.Count-1];

                    jpgimage.EndInit();

                  Image wpfimage = new Image();
                  wpfimage.Source = jpgimage.Clone();
                    lbx.Items.Add(wpfimage);
                    lbx.UpdateLayout();
                    Thread.Sleep(500);


   }));
            }
            mems.Clear();


        }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-01-01 17:39:45

在您的代码中,整个LoadImages主体被调用回主线程。因此,您根本没有多线程解决方案,只是一个复杂的解决方案。

这是我的刺:

代码语言:javascript
复制
// untested
void LoadImages()
{
       // this.Dispatcher.Invoke(DispatcherPriority.Normal, 
       //    new System.Windows.Forms.MethodInvoker(delegate() {
    IService1 svc = ConnectAndGetObject();
    foreach (byte[] imgbytes in svc.GetImageDateWise(datePicker1.DisplayDate, DateTime.Now, "test"))
    {   
        using (MemoryStream mem = new MemoryStream(imgbytes))
        {    
            BitmapImage jpgimage = new BitmapImage();
            jpgimage.BeginInit();    
            jpgimage.CacheOption = BitmapCacheOption.OnLoad;    
            jpgimage.StreamSource = mem;    
            jpgimage.EndInit();

            // only invoke the part actually touching the UI    
            this.Dispatcher.Invoke(DispatcherPriority.Normal, 
              new System.Windows.Forms.MethodInvoker(delegate() {
                  Image wpfimage = new Image();
                  wpfimage.Source = jpgimage; //.Clone();
                  lbx.Items.Add(wpfimage);
                  lbx.UpdateLayout();   } ));

            Thread.Sleep(1000);
        }
    }    
   //  }));
}
票数 4
EN

Stack Overflow用户

发布于 2010-01-01 17:42:36

问题是,非UI线程所做的第一件事就是在UI线程上调用一个委托。最终的结果是大量开销,根本没有并发性。

重新组织代码,以便只在UI线程上执行UI任务。

代码语言:javascript
复制
void LoadImages() 
{ 
    IService1 svc = ConnectAndGetObject(); 
...
Dispatcher.Invoke( () => lbx.Items.Add(wpfimage));
....
} 
票数 2
EN

Stack Overflow用户

发布于 2010-01-01 17:28:50

你的代表做得太多了。这可能是你的问题的原因,再加上你有1秒的睡眠时间。

只需要更新委托中的列表框的代码:

代码语言:javascript
复制
        lbx.Items.Add(wpfimage);
        lbx.UpdateLayout();

如果失败,则会在线程中引发事件,并在主应用程序中订阅该事件,并由此更新UI。

您需要一个这样的方法:

代码语言:javascript
复制
    private void ImageAdded_EventHandler(object sender, ImageAddedEventArgs e)
    {
        Action action = () => ImageAdded(e.Image);
        if (Dispatcher.CheckAccess())
        {
            action();
        }
        else
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, action);
        }
    }

其中ImageAddedEventArgs是一个基于EventArgs的类,它具有图像数据的属性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1989097

复制
相关文章

相似问题

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