在C++中有2种类型的线程:UI Thread和Worker Thread,前者是基于用户界面的有消息循环的线程、后者是没有用户界面的侧重于大时空运算的线程。直接调用Windows相关线程及同步对象的API即可。

在.NET framework进阶编程中,可以用基于delegate的方式来处理界面保持活动,而后台作大运算量或耗时的操作。

应用程序的需求是:点击一个按钮来刷新用户界面上某区域数据相关控件,其内容动态从web service上获取并填充到该控件,而不影响另一区域实时显示数据。

基本的作法是这样的:
1,定义2个delegate及分别对应的处理过程,注意返值和参数要一一对应。一个delegate代表的函数是顶层的异步调用,它会调用另外一个delegate,而另一个delegate代表的函数过程是GUI上会被刷新内容的控件相关的操作,通过System.Control.InvokeRequired判断调用线程与被调用控件是否在同一线程来显式运行System.Control.Invoke(明显地,它们位于不同线程,主要的目的是让同步调用可以复用这段函数代码)。需要特别注意的是,耗时操作要从System.Control.Invoke调用的delegate中分离开,否则跟单线程时效果没有区别,这一点让我困扰了不少时间。
2,定义一个回调函数,用于异步操作结束后的回调(而不是通过调用IAsyncResult接口的轮询方式),里面包括按钮控件的使能恢复和结束异步调用的EndInvoke显示调用。它是位于不同于调用线程的线程池中。

关键代码段如下:

        private void UpdateInquiry()
{ //UI界面的更新放在这里(the other thread) //control operations on GUI such as clear, load data, fresh etc.
...
} private delegate void crossThreadDelegate();
private void UpdateInquiryContainer() //此函数也可用于同步调用
{
//耗时操作一定要放在这里,不要包含在UpdateInquiry(UI界面的更新)中!!!(just like a worker thread as windows API)
this._presenter.TimeConsumingOperation(); if (treeListInquired.InvokeRequired)
{
crossThreadDelegate caller = new crossThreadDelegate(UpdateInquiry);
treeListInquired.Invoke(caller);
}
else
{
UpdateInquiry();
}
} //callback function which is used to end the asynchronous inquiry operation and resume the
//enable state of related controls
public void AsyncRefreshCallback(IAsyncResult result)
{
AsyncRefreshCaller inquiryDelegate = (AsyncRefreshCaller)((AsyncResult)result).AsyncDelegate;
inquiryDelegate.EndInvoke(result); //enable related controls again - there may be an issue thread-safe-related - by OY
if (bCanDemand)
{
dateTimePickerDate.Enabled = true;
btnPrev.Enabled = true;
btnNext.Enabled = true;
btnRefresh.Enabled = true;
}
} private delegate void AsyncRefreshCaller();
private void RefreshInquiry()
{
//disable related controls on GUI
dateTimePickerDate.Enabled = false;
btnPrev.Enabled = false;
btnNext.Enabled = false;
btnRefresh.Enabled = false; //invoke synchronous method asynchronously
AsyncRefreshCaller inquiryDelegate = new AsyncRefreshCaller(UpdateInquiryContainer);
AsyncCallback callback = new AsyncCallback(this.AsyncRefreshCallback);
inquiryDelegate.BeginInvoke(callback, null);
//inquiryDelegate.BeginInvoke(null, null);
}

参考:MSDN(VS2005) - ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_fxadvance/html/c6baed9f-2a25-4728-9a9a-53b7b14840cf.htm

用delegate实现.NET应用程序的同步函数的异步调用-.NET多线程编程实践之一的更多相关文章

  1. nodejs 代码设计模式1:同步函数变异步

    同步函数变异步 1 问题: 1.1 碰到需要调用你刚正在创建的对像. function createServer(data, cb) { data.num = 1; cb(); return data ...

  2. OC 线程操作 - GCD使用 -同步函数,异步函数,串行队列,并发队列

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ // GCD 开几条线程并不是我们 ...

  3. python多线程编程(3): 使用互斥锁同步线程

    问题的提出 上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的 ...

  4. 循序渐进做项目系列(2):最简单的C/S程序——消息异步调用与消息同步调用

    上篇博客 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法 实现了一个最简单的C/S程序,即让服务器来做加法.当时为了通俗易懂采用了消息异步调用的方式.今天我们要采用消息同步调用的方式 ...

  5. 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)

    下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...

  6. 微信小程序中同步 异步的使用

    https://www.jianshu.com/p/e92c7495da76   微信小程序中使用Promise进行异步流程处理 https://www.cnblogs.com/cckui/p/102 ...

  7. Objective-C Http常用API 同步请求与异步请求

    开发iOS应用要调用Http接口.获取Http资源,有一套比较成熟的框架ASIHTTPRequest.而我还是比较喜欢使用原始一点的 API,而它跟其他的面向对象语言有许多共通之处.本文分同步请求和异 ...

  8. C# 委托的三种调用示例(同步调用 异步调用 异步回调)

    首先,通过代码定义一个委托和下面三个示例将要调用的方法: 复制代码 代码如下: public delegate int AddHandler(int a,int b);    public class ...

  9. C# 委托的同步调用和异步调用

    委托的Invoke方法用来进行同步调用.同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行. 同步调用的例子: using System; using System.T ...

随机推荐

  1. 安装composer,以及通过composer安装laravel

    1安装composer http://docs.phpcomposer.com/00-intro.html#Installation-Windows中选择windows安装 下载并且运行 Compos ...

  2. RDMA的基础概念

    一张图可以简单明确的说明,目前RDMA的几种技术的差别: RDMA是remote Direct memory access的简称,有几个最基本的特点: CPU offload kernel bypas ...

  3. mysql 5.7.17 建立主从数据库

    ---恢复内容开始--- 1.确定主/从数据库地址; 2.将主数据库的database dump出来 windows平台用workbench; 其他可以参考: 这位同仁写的比较详细了.我就不谢了.打开 ...

  4. UI设计教程分享:设计一个高质量的logo要从哪方面入手呢?

    有的人觉得logo只是一个简单的图形,对品牌影响无关紧要:但有的人却觉得logo对品牌有较大的影响.其实logo承载着一个公司的品牌形象.公司背景.公司理念等.就像Landor往往给一个企业做logo ...

  5. JSP概述、API、注释

    JSP自带的API包含4个包,可通过Tomcat的官网查看,JSP和EL的API是分开的 javax.servlet.jsp // 包含用于Servlet/JSP容器将JSP页面翻译为Servlet的 ...

  6. vue获取DOM元素并设置属性

    这里我想到了2个方法: 方法一: 直接给相应的元素加id,然后再document.getElementById("id");获取,然后设置相应属性或样式 方法二: 使用ref,给相 ...

  7. Sophus链接错误

    错误指示如下: CMakeFiles/run_vo.dir/run_vo.cpp.o: In function `main': run_vo.cpp:(.text.startup+0x1086): u ...

  8. canvas 实现弹跳效果

    一:创建画布 <canvas width="600" height="600" id="canvas"></canvas& ...

  9. mysql里几个超时配置参数wait_timeout,net_read_timeout等

    以下这些配置项单位都是秒,在mysql命令行中可以使用show global variables like '变量名';可查询配置值. connect_timeout:连接响应超时时间.服务器端在这个 ...

  10. 又一道区间DP的题 -- P3146 [USACO16OPEN]248

    https://www.luogu.org/problemnew/show/P3146 一道区间dp的题,以区间长度为阶段; 但由于要处理相邻的问题,就变得有点麻烦; 最开始想了一个我知道有漏洞的方程 ...