首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF中的等待不会返回到UI线程

WPF中的等待不会返回到UI线程
EN

Stack Overflow用户
提问于 2014-06-27 18:57:04
回答 2查看 409关注 0票数 2

我在WPF4.5 (.net 4.5)中有一个奇怪的行为。我使用关键字等待和异步来运行长操作(例如加载一个大的BitmapImage,图像控件的基础)。问题是服务员没有返回主UI线程,因为我得到了著名的例外:

调用线程无法访问此对象,因为其他线程拥有该对象。

有人能帮我吗?

这里我的代码:

按钮的事件处理程序:

代码语言:javascript
复制
    private void GetExifData_Click(object sender, RoutedEventArgs e)
    {
        // Async method
        (new AnalyzeSingleImage()).RunExif(this);           
    }

main方法(在单独的类中,相同的程序集)

代码语言:javascript
复制
    public async void RunExif(MainWindow win)
    {
      // here I run correctly code on the main UI Thread
      ..
      ..
      // ASYNC !!!
      BitmapImage bi = await LoadImageAsync(fileName);

      Image img = new Image();
      img.Source = bi;  // *********** HERE I GET THE EXCEPTION *************
      ..
      ..
    }

异步方法:

代码语言:javascript
复制
    private Task<BitmapImage> LoadImageAsync(string fileName)
    {
        return Task<BitmapImage>.Run(() => LoadImage(fileName));
    }

长时间法:

代码语言:javascript
复制
    private BitmapImage LoadImage(string fileName)
    {
        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        bi.UriSource = new Uri(fileName);
        bi.CacheOption = BitmapCacheOption.OnLoad;
        bi.EndInit();

        return bi;
    }

有人能帮我吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-29 13:50:24

LoadImage在线程池上运行,因为您使用Task.Run将它推到了那里。在不同的线程上使用UI元素是有效的,但是您必须在同一个线程上一致地访问它们。

您创建的BitmapImage现在绑定到线程池线程。它不能与主UI相结合。

因此,最好的做法是在单个线程上只使用UI。在主线程上创建位图。

如果我还记得WPF正确的话,创建BitmapImage是非常快速的,而且加载图像也是异步的。

票数 2
EN

Stack Overflow用户

发布于 2014-07-16 11:26:08

最后,我使用了以下方法:

在主用户界面上

代码语言:javascript
复制
 BitmapImage bi = await LoadImageAsync(fileName);
            Image img = new Image();
            img.Source = bi; 
            borderImg.Child = img;

漫长的任务..。

代码语言:javascript
复制
 private Task<BitmapImage> LoadImageAsync(string fileName)
    {
        return Task<BitmapImage>.Run(() => LoadImage(fileName));
    }

诀窍是使用冻结成员!!

代码语言:javascript
复制
 private BitmapImage LoadImage(string fileName)
    {

        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        //bi.StreamSource = imgAsStream;
        bi.UriSource = new Uri(fileName);
        bi.CacheOption = BitmapCacheOption.OnLoad;
        bi.DecodePixelWidth = 400; // riduce l'utilizzo di memoria!
        bi.EndInit();
        bi.Freeze(); // IMPORTANTE, ALTRIMENTI RITORNANDO ALLA UI Thread ho un errore!!!!
        return bi;

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

https://stackoverflow.com/questions/24459055

复制
相关文章

相似问题

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