C#多线程之异步编程
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#多线程之异步编程的更多相关文章
- 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换
[源码下载] 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 作者:webabcd 介绍 ...
- 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress
[源码下载] 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithPro ...
- 初步谈谈 C# 多线程、异步编程与并发服务器
多线程与异步编程可以达到避免调用线程异步阻塞作用,但是两者还是有点不同. 多线程与异步编程的异同: 1.线程是cpu 调度资源和分配的基本单位,本质上是进程中的一段并发执行的代码. 2.线程编程的思维 ...
- C++多线程并发---异步编程
线程同步主要是为了解决对共享数据的竞争访问问题,所以线程同步主要是对共享数据的访问同步化(按照既定的先后次序,一个访问需要阻塞等待前一个访问完成后才能开始).这篇文章谈到的异步编程主要是针对任务或线程 ...
- C# - 多线程 之 异步编程
异步编程 同步编程,请求响应模型,同步化.顺序化.事务化. 异步编程,事件驱动模型,以 Fire and Forget 方式实现. 异步编程模式 -§- 异步编程模型 (APM) 模式: IAsyn ...
- 多线程之异步编程: 经典和最新的异步编程模型,async与await
经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...
- 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换
经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...
- c# 中的多线程和异步
前言: 1.异步和多线程有区别吗? 答案:多线程可以说是实现异步的一种方法方法,两者的共同目的:使主线程保持对用户操作的实时响应,如点击.拖拽.输入字符等.使主程序看起来实时都保持着等待用户响应的状态 ...
- Async await 异步编程说明
希望在编程上有些许提高所以 最近连续2篇博客都在说明多线程和异步编程的使用,异步和多线程之间区别请自行百度,因为理解不是特别透彻就不在叙述以免误导大家,这里写下新研究整理 task 和 await ...
随机推荐
- 前端开发利器webStorm
这里推荐一个前端开发工具webStorm.用了大概快半年了,发现所有其他工具无出其右的.目前最新版本已经到4.0.2,半年前还是2.X 相比aptana.dreamweaver.sublime和vim ...
- 自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本
作为测试,在测试工作中一定会经常抓log,有时log收集时间很长,导致log很大,可能达到几G,想找到能打开如此大的log文件的工具都会变得困难:即使log不大时,我们可以直接把log发给开发同学去分 ...
- 读取Pdm文件内容(含源码)
Pdm文件,就是PowerDesigner软件生成的文件,用来设计数据库表结构非常适合.其实,它的文件存储格式就是Xml,网上有很多代码,可以读取pdm文件内容.代码可以使用,但一般只能读取简单的pd ...
- springMvc学习笔记一
什么是springmvc springmvc就是spring框架的一个模块 所以springmvc与spring之间无需通过中间整合层进行整合的. springmvc又是基于mvc的web框架 mv ...
- js在函数中未定义的变量的处理
<html> <head> <script type="text/javascript"> var z=1; function abc(){ x ...
- iOS微信内存监控
WeTest 导读 目前iOS主流的内存监控工具是Instruments的Allocations,但只能用于开发阶段.本文介绍如何实现离线化的内存监控工具,用于App上线后发现内存问题. FOOM(F ...
- 《清华梦的粉碎》by王垠
清华梦的诞生 小时候,妈妈给我一个梦.她指着一个大哥哥的照片对我说,这是爸爸的学生,他考上了清华大学,他是我们中学的骄傲.长大后,你也要进入清华大学读书,为我们家争光.我不知道清华是什么样子,但是我 ...
- 算法提高 矩阵乘法 区间DP
这是神题,n <= 1000,如果是极限数据普通的n^3区间DP怎么可能过?可偏偏就过了. 刘汝佳大哥的训练指南上面说的存在nlgn的算法解决矩阵链乘问题,可是百度都找不到.... AC代码 # ...
- php基本函数的学习(2)
chgrp chgrp — 改变文件所属的组 说明: bool chgrp ( string $filename , mixed $group ) 尝试将文件 filename 所属的组改成 grou ...
- Redis笔记2-发布订阅
发布/订阅"(publish/subscribe)模式可以实现进程间通信,订阅者可以订阅一个或多个频道(channel),而发布者可以向指定的频道发送消息,所有订阅次频道的订阅者都会收到次消 ...