private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
_button.IsEnabled = false;
Task.Factory.StartNew(() =>
Thread.Sleep(5*1000);
Dispatcher.Invoke(new Action(() => _button.IsEnabled = true));
这很好用.但我希望Task返回一些值,例如Boolean.所以我需要使用Task< Boolean>:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
_button.IsEnabled = false;
var task = Task<Boolean>.Factory.StartNew(() =>
Thread.Sleep(5*1000);
return true;
if (task.Result)
_button.IsEnabled = true;
这里我们遇到了UI阻塞问题. UI线程被锁定,直到任务将返回结果.
_button.IsEnabled = false;
您的主线程正在阻塞,因为对Task.Result的调用将等待,直到Task完成.相反,您可以在Task完成后使用Task.ContinueWith()访问Task.Result.对TaskScheduler.FromCurrentSynchronizationContext()的调用导致继续在主UI线程上运行(因此您可以安全地访问_button).
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
_button.IsEnabled = false;
Task<Boolean>.Factory.StartNew(() =>
Thread.Sleep(5*1000);
return true;
}).ContinueWith(t=>
if (t.Result)
_button.IsEnabled = true;
}, TaskScheduler.FromCurrentSynchronizationContext());
如果您使用的是C#5,则可以使用async / await.
async/await 的解决方案刚好解决了当前我遇到的问题,因为异步使用了等待结果返回,所以导致UI卡死状态,
XAML:<Button Name="_button" Click="ButtonBase_OnClick"> Click</Button> CSprivate void ButtonBase_OnClick(object sender, RoutedEventArgs e){ _button.IsEnabled...
虽然使用Dispatcher.Invoke 和模拟winform 里面的DoEvent 但是运行中关闭还是会有异常,而且耗资源高;
第二种 :
DispatcherTimer 失败:UI还是会卡顿;
第三种 :
Timer 建议使用、资源占用少,关闭启动自如。
WPF 支持创建多个 UI 线程,跨窗口的或者窗口内的都是可以的;但是这个过程并不是线程安全的。
你有极低的概率会遇到 WPF 多线程 UI 的线程安全问题,说直接点就是崩溃。本文将讲述其线程安全问题。
此问题现已报告给微软:Creating multi-thread UI has a low probability to crash · Issue #297 · dotnet/wpf
本文内容...
在winform中,如果要执行一个耗时操作,通常会使用进度条ProgressBar来显示耗时操作的进度,在winform中耗时操作的同时更改进度条的值,在UI上面可以看到进度条动态增长。
但是在WPF中(Stylet框架+MVVM开发模式),如果用同样的方法去实现,则会造成UI阻塞,进度条卡死,当耗时操作执行完毕后UI才刷新(参考下图)。
为什么会这样?
先看一下ViewModel
ViewModel定义了用于表示耗时操作进度的两个属性以及耗时操作,这些属性或者方法会在View中被绑定。
在写程序时,有时我们需要连接数据库或者其他服务器,此时可能会消耗很长时间,并出现界面卡死。如果用鼠标点击窗口,会显示“无响应”。这是因为耗时操作在UI线程中,阻塞了UI线程,所以网上大多数建议采用多线程,将耗时操作和UI线程分开。以下以连接数据库为例。
首先要using System.Threading;
然后创建连接数据库的sqlconnection
string connString ...
一、问题的发现
在做项目的过程中,只要有延迟的代码UI界面就会卡住,比如各种网络连接和Thread睡眠等。虽然这样的代码并不多,但整个系统做下来出现这样问题的交互还真不少,对于多线程小白的我来说并不懂的如何去解决这样的问题,只能任由其交互体验差。
但最近实在是忍无可忍,便花了几天的时间来解决这个问题,以下是解决该问题的方法和从UI界面卡住的问题延伸的多线程探索,其中包括自定义加载控件的制作并且应用到实际界面中,也就是在界面“卡住”期间启用加载控件,Dispatcher的使用,BackgroundWork
C#中跨线程访问UI
dotnet中线程资源独占UI元素,不能跨线程访问,可以通过Dispatcher.Invoke的方式调用,但实际处理还是UI线程中,任务量比较大的数据会增加线程的处理压力。
其实还有一种做法,可以通过设置UI元素为只读的方式,跨线程访问。
如BitmapSource跨线程访问,可以调用Freeze设置元素为只读模式。
Aforge.net跨线程传递图像资源,如下:
priva...
在后台线程调用如下代码即可用来判断是否卡顿
private static async Task<bool> CheckDispatcherHangAsync(Dispatcher dispatcher)
var taskCompletionSou...
项目情况如下:程序业务:点击开始之后,从文件中获取数据,将数据显示到界面(按照某种可视化的形式)上,直到文件数据读完或者界面操作停止才会停止数据刷新。
程序能正常运行,但是,当程序开始之后,拖拽、缩放窗体(WPF默认的窗体样式),界面假死,鼠标失去响应,也不能回到任务栏…可以通过按"Win"键恢复,但是恢复之后,界面有可能已经失去正常工作能力了——数据刷新不正确,时序不对等等问题。
原因...
之前做过一个winform的TCP通讯的程序,只要在load函数加一句CheckForIllegalCrossThreadCalls = false;即可。但是到了
wpf里面这句话没了,查阅了很多资料,把我所理解的
wpf多线程分享一下
大部分人百度,查出来的都是这么一个答案:
private void ReciveMsg(object o)//接收函数
this.Dispatcher.Invoke(new Action(delegate
public static void DoEvents()
Application.Current.Dispatcher.Invoke(DispatcherPriority.Render,
new Action(delegate { }));
public void DoEvents()
DispatcherFrame frame = new DispatcherFrame();
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.UriSource = new Uri("image.jpg", UriKind.Relative);
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
// 在UI线程上更新Image控件的Source属性
await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
MyImage.Source = bitmapImage;
3. 在需要加载图片的地方调用上述异步方法:
await LoadImageAsync();
通过上述步骤,我们可以在WPF中实现异步加载本地图片。首先,使用`BitmapImage`类来读取本地图片文件,并通过异步方式进行加载。然后,在UI线程上使用`Dispatcher.BeginInvoke`方法更新Image控件的Source属性,确保操作在UI线程上执行,避免线程冲突。最后,调用异步方法即可实现异步加载本地图片。