简体   繁体   English

UI线程上BitmapImage操作的替代方法?

[英]Alternative to BitmapImage operations on the UI thread?

I would like to create a worker class that can retrieve laggy resources (eg from a database or over a network), and prepare them for later, zero-lag display on the UI. 我想创建一个工作器类,该类可以检索滞后的资源(例如,从数据库或通过网络),并为以后在UI上零延迟显示做好准备。 That worker class should not be bound to the UI or to the UI thread ie it should be able to run anywhere. 该工作者类不应绑定到UI或UI线程,即它应该能够在任何地方运行。 When done, it's output will be a populated array of some image container class that the UI can work with easily. 完成后,其输出将是UI可以轻松使用的某些图像容器类的填充数组。

My first thought was to use the BitmapImage class as the image container; 我首先想到的是使用BitmapImage类作为图像容器; however that inherits from the DependencyObject class, which will restrict access from any non-UI thread. 但是,它继承自DependencyObject类,这将限制从任何非UI线程的访问。 As @Filip pointed out in my earlier form of this question, this is not inherently a problem, but it would restrict the generality of my worker class. 正如@Filip在此问题的较早形式中指出的那样,这并不是天生的问题,但是它将限制我的工人阶级的普遍性。

Is there a better Windows class that I can use as the basis for the image container, and then convert to BitmapImage on the UI thread at bind time? 有没有更好的Windows类可以用作图像容器的基础,然后在绑定时转换为UI线程上的BitmapImage? Or a better way altogether? 还是完全更好的方法? Here is some pseudo code to indicate what I'm trying to do, using an array of URIs for the source images. 这是一些伪代码,使用源图像的URI数组来指示我要执行的操作。

In the worker class 在工人阶级

ImageContainerClass[] prepImages(Uri[] uriSet)
{
    ImageContainerClass[] iccSet = new ImageContainerClass[uriSet.Length];
    for (int i = 0; i < iccSet.Length; i++)
        iccSet[i] = new ImageContainerClass.retrieveImage(uriSet[i]); 
    return iccSet;
} 

On the UI thread (at some later time): 在UI线程上(稍后):

BitmapImage bmi = new BitmapImage();
var image = iccSet[i].getImage();
<<some operation to set the source of bmi to the image>>
someImage.Source = bmi;

I think loading images into BitmapImage happens on a background thread in the platform, so there shouldn't be a need for you to do it. 我认为将图像加载到BitmapImage中是在平台的后台线程上进行的,因此不需要您这样做。 You could probably use BitmapDecoder on a background thread if you needed to and then maybe push a pixel buffer into a WriteableBitmap , but you wouldn't gain much from it. 如果需要,可以在后台线程上使用BitmapDecoder ,然后将像素缓冲区推入WriteableBitmap ,但不会从中获得很多好处。 If you really want to force all the code to a background thread then you can use DirectX interop and have a completely separate background render thread for your stuff. 如果您真的想将所有代码强制为后台线程,则可以使用DirectX interop并为您的内容提供一个完全独立的后台渲染线程。

OK, so here's a solution that appears to work. 好的,这是一个可行的解决方案。

The following code will run happily on a non-UI thread: 以下代码将在非UI线程上愉快地运行:

    internal async Task<InMemoryRandomAccessStream> getImage(Uri uri)
    {
        try {
            var httpClient = new HttpClient();
            IBuffer iBuffer = await httpClient.GetBufferAsync(uri);
            byte[] bytes = iBuffer.ToArray();
            InMemoryRandomAccessStream ims = new InMemoryRandomAccessStream();
            DataWriter dataWriter = new DataWriter(ims);
            dataWriter.WriteBytes(bytes);
            await dataWriter.StoreAsync();
            ims.Seek(0);
            return ims;
        } catch (Exception e) { return null; }
    }

Then, the following code may be executed on the UI thread when the image needs to be displayed: 然后,当需要显示图像时,可以在UI线程上执行以下代码:

BitmapImage bmi = new BitmapImage();
bmi.SetSource(ims);
someImage.Source = bmi;

I'm sure this can be cleaned up by people more familiar with the relevant frameworks, but hopefully this will help others. 我相信可以由更熟悉相关框架的人员来解决此问题,但希望这会对其他人有所帮助。 My thanks to @Filip for putting me on the right track. 感谢@Filip使我走上正轨。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在后台线程中加载BitmapImage会导致UI线程停顿 - Load BitmapImage in background thread causes UI thread to stutter 如何将BitmapImage从后台线程传递到WPF中的UI线程? - How do you pass a BitmapImage from a background thread to the UI thread in WPF? 在非UI线程上使用BitmapImage(或其他UI命名空间类)是否受到限制? - Is there a restriction on using a BitmapImage (or other UI namespace classes) on a none- UI thread? 在UI线程上分组多个异步操作 - Group multiple async operations on the UI thread UI线程中Task.Wait的替代方案 - Alternative for Task.Wait in UI thread 为什么后台线程中的图形操作会阻止主UI线程中的图形操作? - Why do Graphics operations in background thread block Graphics operations in main UI thread? 在同步操作上使用async / await(主要停留在UI线程上) - Use async/await on synchronous operations (mainly to stay on UI thread) 什么是Thread.Join()的替代品,以克服UI冻结问题 - What is alternative of Thread.Join() to overcome UI freezing issue 在后台线程 WP7 上创建 BitmapImage - Creating BitmapImage on background thread WP7 UI线程中与Dispatcher.PushFrame和Application.DoEvents的互斥操作 - Mutual exclusive operations in UI thread with Dispatcher.PushFrame and Application.DoEvents
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM