![](/img/trans.png)
[英]Why to split the tasks not running on UI thread to make WPF app more responsive?
[英]WPF UI not responsive in spite of process running in a seperate thread. Why?
在WPF中使用线程对我来说没有任何区别。 UI仍然没有响应。
这是我的代码:
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);
}
}
}));
}
更新的工作代码:
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();
}
在您的代码中, 整个 LoadImages
主体被直接调用回主线程。 因此,您根本没有多线程解决方案,只有一个复杂的解决方案。
这是我的目的:
// 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);
}
}
// }));
}
问题在于,非UI线程要做的第一件事是在UI线程上调用委托。 最终结果是大量的开销,根本没有并发。
重新组织代码,以便仅UI任务在UI线程上完成。
void LoadImages()
{
IService1 svc = ConnectAndGetObject();
...
Dispatcher.Invoke( () => lbx.Items.Add(wpfimage));
....
}
您在代表中做得太多。 这可能是导致您出现问题的原因,再加上在那里停留1秒钟的睡眠时间。
只需提供更新委托中列表框的代码即可:
lbx.Items.Add(wpfimage);
lbx.UpdateLayout();
失败会在您的线程中引发一个事件,并在您的主应用程序中订阅它,并从中更新UI。
您将需要以下方法:
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
的类,该类具有图像数据的属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.