c#中异步编程,主要有两种方法: 1、委托的异步调用; 2、Task的await,async (c# 4.5)

我们来看例子:

         /// <summary>
/// 异步保存网页,url:网页地址,path:要保存的位置
/// </summary>
private void SavePageAsync(string url, string path)
{
Func<string, string, bool> fun = SavePageSingleFile;
IAsyncResult result = fun.BeginInvoke(url, path, new AsyncCallback(SavePageCompleted), null);
}

Func,是系统定义好的委托类型,当然也可以自定义委托了,委托的本质是一个类,它有一个BeginInvoke 异步调用方法。SavePageSingleFile方法是委托要执行的方法:

         private bool SavePageSingleFile(string url, string path)
{
bool result = false;
try
{
CDO.Message message = new CDO.MessageClass();
ADODB.Stream stream = null;
message.MimeFormatted = true;
message.CreateMHTMLBody(url, CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
stream = message.GetStream();
stream.SaveToFile(path, ADODB.SaveOptionsEnum.adSaveCreateOverWrite);
message = null;
stream.Close(); result = true;
}
catch (Exception ex)
{
Logger.Debug("保存文件出错:" + ex.Message);
}
return result;
}
  
委托任务完成后的回调方法 SavePageCompleted:
       private void SavePageCompleted(IAsyncResult result)
{
try
{
var handler = (Func<string, string, bool>)((AsyncResult)result).AsyncDelegate;
var r = handler.EndInvoke(result); this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
this.Opacity = ; if (CloseWaittingWindow != null)
{
CloseWaittingWindow();
}
this.Cursor = System.Windows.Input.Cursors.Hand; MessageTip tip = new MessageTip();
if (r)
{
tip.Show("保存网页", "文件保存成功");
}
else
{
tip.Show("保存网页", "文件保存失败");
}
}
);
}
catch (Exception ex)
{
Logger.Debug("保存页面文件出错:" + ex.Message);
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
new MessageTip().Show("保存网页", "文件保存出错");
this.Opacity = ; if (CloseWaittingWindow != null)
{
CloseWaittingWindow();
}
this.Cursor = System.Windows.Input.Cursors.Hand;
}
);
}
}

最后看下 SavePageAsync 方法的调用:

         /// <summary>
/// 保存当前页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSavePage_Click(object sender, RoutedEventArgs e)
{
if (this.DBVisitViewModel.CanSavePageExcute)
{
string url = this.WebPageBrower.Url.AbsoluteUri;
if (!Tool.CheckUrl(url))
{
new MessageTip().Show("保存页面", "当前页面无法保存");
return;
} SaveFileDialog sfd = new SaveFileDialog(); sfd.InitialDirectory = @"D:\";
sfd.Filter = "mht file|*.mht"; if (sfd.ShowDialog() == DialogResult.OK)
{
if (OpenWaittingWindow != null)
{
this.Cursor = System.Windows.Input.Cursors.Wait;
SavePageAsync(url, sfd.FileName); this.Opacity = 0.8;
OpenWaittingWindow("正在保存网页,请稍等...");
}
}
}
}

在framework 4.0的时候,委托异步调用显得很方便,到了4.5的时候,我们可以用Task实现异步调用。改下上面的例子:

        private async void SavePageAsync(string url, string path)
{
var r = await SavePageSingleFile(url, path); try
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
this.Opacity = ; if (CloseWaittingWindow != null)
{
CloseWaittingWindow();
}
this.Cursor = System.Windows.Input.Cursors.Hand; MessageTip tip = new MessageTip();
if (r)
{
tip.Show("保存网页", "文件保存成功");
}
else
{
tip.Show("保存网页", "文件保存失败");
}
}
);
}
catch (Exception ex)
{
Logger.Debug("保存页面文件出错:" + ex.Message);
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
new MessageTip().Show("保存网页", "文件保存出错");
this.Opacity = ; if (CloseWaittingWindow != null)
{
CloseWaittingWindow();
}
this.Cursor = System.Windows.Input.Cursors.Hand;
}
);
} }
static async Task<bool> SavePageSingleFile(string url, string path)
{
return await Task.Run(() =>
{
bool result = false;
try
{
CDO.Message message = new CDO.MessageClass();
ADODB.Stream stream = null;
message.MimeFormatted = true;
message.CreateMHTMLBody(url, CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
stream = message.GetStream();
stream.SaveToFile(path, ADODB.SaveOptionsEnum.adSaveCreateOverWrite);
message = null;
stream.Close(); result = true;
}
catch (Exception ex)
{
Logger.Debug("保存文件出错:" + ex.Message);
}
return result;
});
}

第5行后的try,catch语句块,就是保存网页后的回调,它的执行是在子线程中,因此,在wpf 中要用 Dispatcher(回调中牵扯到对页面的操作)。为了简化这一例子,我这儿给出一个简单的可以执行的例子:

   static void Main(string[] args)
{
Add(,);
Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("main Thread go on sth");
Console.Read();
} private async static void Add(int x, int y)
{
Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
var t = await TestAsync(x,y);
Console.WriteLine("正在等待完成任务,当前线程:"+Thread.CurrentThread.ManagedThreadId);  Console.WriteLine("运行结果:" + t);
}
static async Task<int> TestAsync(int x, int y)
{
return await Task.Run(() =>
{
Thread.Sleep();
Console.WriteLine("子线程:" + Thread.CurrentThread.ManagedThreadId);
return x + y;
});
}

运行结果:

异步编程主要是为了解决耗时的任务占用主线程的问题,比如ajax的异步调用,不会导致页面卡死。好了,今天就谈到这里,该吃中午饭了。

C#多线程之异步编程的更多相关文章

  1. 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    [源码下载] 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 作者:webabcd 介绍 ...

  2. 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress

    [源码下载] 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithPro ...

  3. 初步谈谈 C# 多线程、异步编程与并发服务器

    多线程与异步编程可以达到避免调用线程异步阻塞作用,但是两者还是有点不同. 多线程与异步编程的异同: 1.线程是cpu 调度资源和分配的基本单位,本质上是进程中的一段并发执行的代码. 2.线程编程的思维 ...

  4. C++多线程并发---异步编程

    线程同步主要是为了解决对共享数据的竞争访问问题,所以线程同步主要是对共享数据的访问同步化(按照既定的先后次序,一个访问需要阻塞等待前一个访问完成后才能开始).这篇文章谈到的异步编程主要是针对任务或线程 ...

  5. C# - 多线程 之 异步编程

    异步编程 同步编程,请求响应模型,同步化.顺序化.事务化. 异步编程,事件驱动模型,以 Fire and Forget 方式实现. 异步编程模式  -§- 异步编程模型 (APM) 模式: IAsyn ...

  6. 多线程之异步编程: 经典和最新的异步编程模型,async与await

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  7. 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  8. c# 中的多线程和异步

    前言: 1.异步和多线程有区别吗? 答案:多线程可以说是实现异步的一种方法方法,两者的共同目的:使主线程保持对用户操作的实时响应,如点击.拖拽.输入字符等.使主程序看起来实时都保持着等待用户响应的状态 ...

  9. Async await 异步编程说明

    希望在编程上有些许提高所以 最近连续2篇博客都在说明多线程和异步编程的使用,异步和多线程之间区别请自行百度,因为理解不是特别透彻就不在叙述以免误导大家,这里写下新研究整理 task  和 await ...

随机推荐

  1. Mybatis使用总结-思维导图

    目前使用到Mybatis的总结,缓存还未涉及:

  2. 【Unity3D技术文档翻译】第1.9篇 使用 Unity AssetBundle Browser tool (AssetBundle系列完结)

    上一章:[Unity3D技术文档翻译]第1.8篇 AssetBundles 问题及解决方法 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced D ...

  3. WinForm中ClickOnce发布至广域网

    ClickOnce智能客户端,是微软提供比较早的一项技术,用于实现WinForm开发的应用程序能够自动更新,省去给每台客户端升级带来的困扰. 从网上的贴子里看,有的说好用,有的说不好用.客观的说,微软 ...

  4. WinXP系统下Opencms的安装与配置

    1.WinXP系统下安装opencms (1)mysql已安装5.1.40 cmd命令行:mysql   -uroot  -proot (2)OpenCMS在安装时要求MySQL系统变量“max_al ...

  5. 关于eclipse的mysql连接配置

    打开eclipse,选择Window→Open Perspective→Other→Database Development,然后在右边的导航栏右键点击Database Connections文件夹, ...

  6. Qt 信号如何自动连接槽函数?

    on_objectName_signal [static] void QMetaObject::connectSlotsByName(QObject *object) void on_<obje ...

  7. ES磁盘分配不均问题

    最近es集群磁盘空间告警,日志又没地方可以迁移,然后申请了新的服务器,一次性加入8台新的服务器 新增了32个新的数据节点,至此,我们的主集群已经到达85个数据节点的规模,整个集群数据已达到PB级别,终 ...

  8. Storm业务功能

    监控平台当前使用storm对日志进行流式分析计算,用于支撑监控数据清洗,后来逐渐在storm上搭建起数据在线关联,数据离线关联,明细数据清洗,日志搜索等功能,本章节对各功能进行简要概述. 对storm ...

  9. linux ftp及C/S服务架构

    乱码转换工具使用convmv软件:windows中文字符编码为GB2312 linux中文字符编码为utf-8选项:-f:源文件中中文字符编码-t:转换成字符编码-r:代表递归--notest:不测试 ...

  10. 工作中常用的linux命令(1)

    1.cd :进入一个目录,例如进入/home/admin目录:cd /home/admin 2.pwd :查看当前所在目录:如图: 3.ls :列出当前目录下的所有文件: 4.ll :列出当前目录下的 ...