WPF异步回调时回调函数如何获取异步函数产生的变量

简介: 原文:WPF异步回调时回调函数如何获取异步函数产生的变量  有这么一个问题,WPF在使用异步回调的时候,回调函数需要用到异步函数里产生的一个变量,例如异步函数里查询数据库得到了一个DataTable,如何传递给回调函数呢? 【方案一】使用全局变量   很容易想到的是用全局变量,这也是最简单的办法。
原文: WPF异步回调时回调函数如何获取异步函数产生的变量

  有这么一个问题,WPF在使用异步回调的时候,回调函数需要用到异步函数里产生的一个变量,例如异步函数里查询数据库得到了一个DataTable,如何传递给回调函数呢?

【方案一】使用全局变量

  很容易想到的是用全局变量,这也是最简单的办法。但是如果我想循环调用呢,例如回调函数判断异步函数执行完之后的DataTable有没有数据,有数据则继续异步(BeginInvoke),这时候如果使用全局变量可能会出现意外情况,因为是循环调用,回调函数使用的DataTable是不是你想要的那个值就比较难说了。

【方案二】闭包

  这也是一个比较常规的办法,闭包的话就方便内部变量传递了,写法如下:

private void QueryDateBase()
        {
            DataTable dtTarget = new DataTable();//共享变量

            Action handler = delegate()//异步匿名委托
            {
                dtTarget = XXX查询数据库;
            };
            
            AsyncCallback functionCallBack = delegate(IAsyncResult asyResult)//回调匿名委托
            {
                handler.EndInvoke(asyResult);
                if (dtTarget.Rows.Count > 0)
                {
                    QueryDateBase();
                }
            };

            handler.BeginInvoke(functionCallBack, null);
        }
  这就是所谓的闭包了,使用了匿名委托,回调函数和异步函数定义在一个方法体内,这样变量就能共享,类似的,WPF的动画有个Completed事件,如果它里面要使用到开始执行时的一些变量,也能使用此法共享变量。这里有两点要注意:
  1. handler注册的方法里不能涉及到任何UI控件和UI逻辑,否则异步方法没有调用完就会执行EndInvoke方法,导致调用错误
  2. 如果必须要用到UI控件或者UI逻辑,可以用Application.Current.Dispatcher.Invoke(new Action(() => { ...}));

  那么,能不能不使用全局变量呢?

【方案三】使用返回值

  使用带返回值的委托,这样在委托EndInvoke的时候就可以获得委托的返回值了,代码看起来是这样的:

    public class Student
    {
        public Func<DataTable> queryHandler;

        public Student()
        {
            queryHandler = QueryDateBase;
            queryHandler.BeginInvoke(CallBack, null);
        }

        private DataTable QueryDateBase()
        {
            DataTable dtTarget = XXX查数据库;
            return dtTarget;
        }

        private void CallBack(IAsyncResult ar)
        {
            DataTable dtCallBack = queryHandler.EndInvoke(ar);
            if (dtCallBack.Rows.Count > 0)
            {
                queryHandler.BeginInvoke(CallBack, null);
            }
        }
    }
  个人认为这是比较正统的写法,精准的返回值,没有全局变量。其实Winform也是如此,使用起来并无差异,只是wpf涉及UI时要注意。
目录
相关文章
|
算法 C#
解决WPF中重载Window.OnRender函数失效问题
原文:解决WPF中重载Window.OnRender函数失效问题 今天实验一个绘图算法的时候,偶然发现重载Window.OnRender的方法是没有效果的。 public partial class MainWindow : Window { public ...
942 0
|
C# 开发工具
WPF 海康威视网络摄像头回调方式实现断连提示,降低时延
原文:WPF 海康威视网络摄像头回调方式实现断连提示,降低时延 项目需要使用海康威视网络摄像头接入实时视频数据,使用海康威视官方SDK开发,发现没有断连提示的功能,故开发了一个断连提示的功能 在开发过程中遇到以下问题: 1、延迟2S左右,后咨询海康威视技术支持,需要设置子码流,需要减小缓冲区,故使用PlayM4_SetDisplayBuf接口把缓冲区减小为1,,设置后时延0.3S,基本符合需求。
2140 0
|
C#
WPF使用异步+绑定的方式处理大数据量
原文:WPF使用异步+绑定的方式处理大数据量      WPF的优势在于界面处理,即使是这样,在面对大数据量的时候也免不了界面假死,同一个线程里处理界面跟大数据量,这是不可避免的。解决办法还是有的,可以使用分页加载,虚拟加载,动态加载,增加条件限制...      比较好的解决办法是使用异步+绑定的方式,即绑定控件的数据源,异步获取数据。
1241 0
|
JSON C# 数据格式
【WPF/C#】联网异步获取二进制文件(如图片)的流程
原文:【WPF/C#】联网异步获取二进制文件(如图片)的流程 步骤: 联网异步获取Json数据。 使用Json.NET工具,反序列化Json为对应的实体类,获得该实体类的对象。 从对象身上获取图片路径(实体类中定义了头像图片是string类型的文件路径)。
1334 0
|
C#
如何自定义WPF项目的Main函数
原文:如何自定义WPF项目的Main函数   与Winform项目不同,WPF项目的Main函数在项目生成的时候,系统自动在后台为我们生成。
864 0
|
C# C++
WPF附加属性的Set函数不调用的问题
原文:WPF附加属性的Set函数不调用的问题 今天写程序的时候用到了附加属性,我是用VS内置的propa的代码段来实现的,代码如下:     class Attach    {        public static bool GetIsEnabl...
862 0
|
C#
WPF中的动画——(四)缓动函数
原文:WPF中的动画——(四)缓动函数 缓动函数可以通过一系列公式模拟一些物理效果,如实地弹跳或其行为如同在弹簧上一样。它们一般应用在From/To/By动画上,可以使得其动画更加平滑。     var widthAnimation = new DoubleAnimation()    {    ...
993 0
|
C#
WPF 用Main函数方式启动程序
原文:WPF 用Main函数方式启动程序 WPF默认程序启动:新建project后自动生成的App.xaml中指定程序启动方式(StartupUri="MainWindow.xaml"),如下代码所示,启动MainWindow页面                    WPF用Main函数方式启动程序:自己写Main函数作为启动点 1.
1414 0
|
C#
WPF换肤之七:异步
原文:WPF换肤之七:异步 在WinForm时代,相信大家都遇到过这种情形,如果在程序设计过程中遇到了耗时的操作,不使用异步会导致程序假死。当然,在WPF中,这种情况也是存在的,所以我们就需要寻找一种解决方法来让程序界面响应和耗时操作异步进行,那么上述假死的情况就不会发生了。
1234 0