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时要注意。

时间: 2024-11-08 08:39:23

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

node.js 在函数内获取当前函数

js 如何在函数体内部知道 自己在哪个函数内运行呢? 打比方: function a() { // 我想在这里知道我的函数名a和函数function a () {...} } 使用Error的调用栈可以匹配到当期执行的函数: // 获取正在执行的函数 function getExecFunction() { let names = new Error().stack.match(/at (.*?) /g); let name = names[1].replace('at ', '').trim(

JSF页面中使用js函数回调后台bean方法并获取返回值的方法

由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的,很可能会误导使用者. 相对来说,看国内的那些仅仅是翻译过来的文章或书籍不如直接看国外的官方文档或资料来的实在,在我讲述jsf页面中如何使用js调用后台bean方法之前,先给大家说几个国外的资料.在primefaces官方网站上,你可以搜索到几乎所有你需要的东西,primefaces官网为:http:

IT小鲜肉 Widgets Tree 单选、多选、相关回调函数、获取选中的节点功能

写一个树控件并没有想象中的那么容易,今天又花了我一个1个多小时,主要为IT小鲜肉 Widgets Tree控件添加了 单选.多选.选择前和选择后两个回调函数.获取选中节点的功能.后面会继续努力完善这个树控件. 1.通过设置初始化时候的选项{select:true}开启单选,通过设置初始化时候的选项{select:{type:'multiple'}}开启多选 使用实例代码如下: 运行效果如下: 2.添加了onBeforeSelect回调函数,用来实现自定义选择,如果该函数返回false会中断默认的

LVC函数重要参数 EDT_CLL_CB:退出可编辑单元格时回调

6. I_GRID_SETTINGS 参数属性该参数用于设置Grid相关参数(打印.单元格回调):类型为:LVC_S_GLAY,该结构包括:01) COLL_TOP_P:最小化 TOP_OF_PAGE02) COLL_END_L:最小化 END_OF_LIST03) TOP_P_ONLY:仅打印TOP_OF_PAGE04) EOL_P_ONLY:仅打印END_OF_LIST05) NO_COLWOPT:不优化打印的列宽***************************************

Unity 之 C# 利用回调函数实现C++匿名函数

做C++开发的都用过匿名函数非常好用,但是C#开发怎么实现呢?前几天做一个拍照功能的时候,我偶然发现某个函数如果是C++的话,用匿名函数太好了,于是开始研究C#的回调,代理,委托等,最后总算是实现了我想要的吧,不知道到底算什么调用.有大神的话可以给出评价. 参考文章: 详解C#委托,事件与回调函数Unity3D研究院之利用C#实现代理模式(四十) 直接上代码吧,不废话了.A类是委托的定义类,B类是调用委托(匿名函数)的类. using UnityEngine; using System.Coll

python第三十七天,GIL全局解释器锁*****,线程池与进程池 同步异步,阻塞与非阻塞,异步回调

GIL全局解释器锁 1.什么是GIL 官方解释:'''In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe

.NET异步编程之回调

C#中异步和多线程的区别是什么呢?异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性.甚至有些时候我们就认为异步和多线程是等同的概念.但是,异步和多线程还是有一些区别的.而这些区别造成了使用异步和多线程的时机的区别. 异步操作的本质 所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础. 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘.光驱的技术规格中都有明确DMA的模式指标,其实网卡.声卡.显卡也是有DMA功能的.DMA

JavaScript异步编程__“回调地狱”的一些解决方案

异步编程在JavaScript中非常重要.过多的异步编程也带了回调嵌套的问题,本文会提供一些解决"回调地狱"的方法. setTimeout(function () { console.log('延时触发'); }, 2000); fs.readFile('./sample.txt', 'utf-8', function (err, res) { console.log(res); }); 上面就是典型的回调函数,不论是在浏览器中,还是在node中,JavaScript本身是单线程,因此

异步调用与回调机制,协程

1.异步调用与回调机制 上一篇我们已经了解到了两组比较容易混淆的概念问题,1.同步与异步调用 2.阻塞与非阻塞状态.在说到异步调用的时候,说到提交任务后,就直接执行下一行代码,而不去拿结果,这样明显存在缺陷,结果是肯定要拿的,这辈子都肯定是要拿到这个结果的,没有这个结果后面的活又不会干,没办法,只能去拿结果的,那么问题是异步调用提交任务后,如何实现既要拿到结果又不需要原地等的理想状态呢?专门为异步调用配备了一个方法--回调机制 先来想想我们之前是怎么拿到一个函数的结果,就传给另外一个函数取执行,