我有一个WPF应用程序,它使用一个组件,该组件会在位图可用时将位图发送到我的应用程序,并在传递给该组件的委托(delegate)中接收这些位图。
我为此过程创建了一个新线程,该线程工作得很好,位图作为MemoryStream出现,我只是在Dispatcher.BeginInvoke
方法调用中从该流创建了BitmapSource对象。在拥有BitmapSource对象之后,将它们添加到StackPanel中,以便用户可以看到可用的图像队列。到目前为止,一切都很好...
问题在于这些位图非常大,例如3000x2000 +像素,创建这些位图并将其添加到队列大约需要50毫秒,并且在执行此代码时,BeginInvoke调用中的onde会阻塞UI这次,这将导致非常烦人的行为(要重现此问题,只需每5秒调用Thread.Sleep(50)
一次)。
如何解决此问题,以便用户始终保持响应状态?
谢谢!
最佳答案
您可能要考虑两个想法:
以下代码执行上面的#1:
Window1.xaml
<Window x:Class="BitmapFrameDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Image Name="image"/>
</Grid>
</Window>
Window1.xaml.cs
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace BitmapFrameDemo {
public partial class Window1 : Window {
private Thread thread = null;
private Dispatcher dispatcher = null;
private void ThreadMain() {
// obtain the image memory stream
WebRequest request = WebRequest.Create("http://stackoverflow.com/content/img/so/logo.png");
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
// create a bitmap source while still in the background thread
PngBitmapDecoder decoder = new PngBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
BitmapFrame frame = decoder.Frames[0];
// freeze the bitmap source, so that we can pass it to the foreground thread
BitmapFrame frozen = (BitmapFrame) frame.GetAsFrozen();
dispatcher.Invoke(new Action(() => { image.Source = frozen; }), new object[] { });
}
public Window1() {
InitializeComponent();
dispatcher = Dispatcher.CurrentDispatcher;
thread = new Thread(new ThreadStart(this.ThreadMain));
thread.Start();
}
}
}
alt text http://www.freeimagehosting.net/uploads/66bdbce78a.png