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:&lt;Button Name="_button" Click="ButtonBase_OnClick"&gt; Click&lt;/Button&gt; 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线程上执行,避免线程冲突。最后,调用异步方法即可实现异步加载本地图片。