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. eclipse 使 用Ctrl+鼠标左键进入mapper.xml文件的方法

    在 >eclipse MarketPlace中下载>Mybatipse 插件安装重启即可完成

  2. HTML/CSS 知识点

    整个前端开发的工作流程 产品经理提出项目需求 UI出设计稿 前端人员负责开发静态页面(跟前端同步的后台人员在准备数据) 前后台的交互 测试 产品上线(后期项目维护) 互联网原理 当用户在浏览器输入网址 ...

  3. Tomcat8.5.24日志自动清理(maxDays)功能探究

    前言 测试人员反馈tomcat目录下的日志占用空间很大,需要自动清理.接到这个反馈时,想象着应该是一个很简单的功能,tomcat应该已经实现了日志的自动清理功能.于是乎,我先到网上查询了如何自动清除t ...

  4. 编程中&和&&的区别

    逻辑电路中用&: 与门电路,全真为真,有假为假. 编程中:&表示取地址符(C)和 按位与(非bool类型时,转换成二进制,按位与运算). &&表示逻辑与运算,& ...

  5. AES-256加密解密

    /// <summary> /// AES-256加密 /// </summary> /// <param name="toEncrypt">& ...

  6. 简单的GIT上传

    简单的GIT上传 上传项目时先新建一个 文件夹 mkdir test 然后在切换到test文件夹中然后把github 中的项目拷贝下来 git glone url 然后git init 查看文件 然后 ...

  7. 多项式A除以B

    这个问题我是在PAT大区赛题里遇见的.题目如下: 多项式A除以B(25 分) 这仍然是一道关于A/B的题,只不过A和B都换成了多项式.你需要计算两个多项式相除的商Q和余R,其中R的阶数必须小于B的阶数 ...

  8. jquery 图片转为base64

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  9. 新手福音︱正则表达式小工具RegExr

    由于之前在做NLP的内容,势必会接触正则表达式,但是呢,又觉得这个学不明白- 于是,这个工具还是蛮不错的,相当于在线正则速查+验证小工具,对于我这样的新手值得去玩玩. github:https://g ...

  10. Java获取当前的日期和时间

    Java获取当前的日期和时间 1.具体实现方法如下 /** * @Title:DateTime.java * @Package:com.you.model * @Description:获取当前的日期 ...