,,C#线程 BeginInvoke和EndInvoke使用方法

,,C#线程 BeginInvoke和EndInvoke使用方法

本文开始C#线程系列讲座之一,即如何使用BeginInvoke和EndInvoke。有需要的朋友可以参考一下。

语言:C#3.0

IDE:Visual Studio 2008

一、C#线程概述

在操作系统中,一个进程必须包含至少一个线程,然后,在某个时刻,需要同时执行同一个进程中的多个任务,或者为了提供者的性能,需要将要执行的任务拆分成多个子任务。这需要在同一个进程中打开多个线程。我们用C#写一个应用程序(控制台或者桌面),然后运行这个程序,打开windows任务管理器。此时,我们将看到该应用程序中包含的线程数,如下图所示。

如果任务管理器没有“线程数”列,您可以[查看][选择列]显示“线程数”列。从上图可以看出,几乎所有的进程都有两个以上的线程。可见,线程是提升应用程序性能的重要手段之一,尤其是在多核CPU机器上。

二、用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程 c#中使用线程的方式有很多种。使用委托的BeginInvoke和EndInvoke方法就是其中之一。BeginInvoke方法可以使用线程异步执行委托指向的方法。然后通过EndInvoke方法获取方法的返回值(EndInvoke方法的返回值就是被调用方法的返回值),或者确定方法已经被成功调用。我们可以通过四种方式从EndInvoke方法获得返回值。

第三,直接使用EndInvoke方法获取返回值。

当使用BeginInvoke异步调用方法时,如果方法没有完成,EndInvoke方法将一直阻塞,直到被调用的方法完成。如下面的代码所示:

复制代码如下:使用System使用系统。集合。泛型;使用系统。Linq使用系统。文本;使用系统。穿线;

命名空间my thread { class program { private static int new task(intms){ console . writeline(' task start ');线程。睡眠(毫秒);Random Random=new Random();int n=随机。下一个(10000);控制台。WriteLine(“任务已完成”);返回n;}

私有委托int new task delegate(int ms);

static void Main(string[]args){ new task delegate task=new task;IAsyncResult asyncResult=task。BeginInvoke(2000,null,null);

//EndInvoke方法将在result=task中被阻止2秒钟。endinvoke(async result);控制台。WriteLine(结果);} } }

运行上述程序后,由于newTask方法被Sleep延迟了2秒,程序直到2秒后才输出最终结果(一个随机整数)。如果不调用EndInvoke方法,程序会立即退出。这是因为用BeginInvoke创建的线程是后台线程。一旦所有前台线程退出(主线程是前台线程),这个线程将结束线程并退出程序,不管后台线程是否已经执行完。前台和后台线程的细节将在后面的部分解释。

读者可以用上面的程序做下面的实验。首先,在Main方法的开头添加以下代码:

复制代码如下:Thread。睡眠(10000);

在执行下面的代码之前,延迟Main方法10秒钟,然后按Ctrl+F5运行程序,打开企业管理器,观察当前程序中的线程数。假设线程数为4,10秒后,线程数将增加到5。这是因为调用BeginInvoke方法时,会建立一个线程来异步执行newTask方法,所以线程数会增加一个。

四、使用IAsyncResult asyncResult属性来判断异步调用是否完成

虽然上面的方法可以很好的实现异步调用,但是当调用EndInvoke方法得到调用结果时,整个程序就跟死了一样,不会让用户感觉太好。所以我们可以用asyncResult来判断异步调用是否完成,并显示一些提示信息。这样做可以增加用户体验。代码如下:

复制代码如下:static void main(string[]args){ newtaskdelegatetask=new task;IAsyncResult asyncResult=task。BeginInvoke(2000,null,null);

而(!异步结果。IsCompleted) {控制台。写(' * ');线程。睡眠(100);}//因为异步调用已经完成,EndInvoke会立即返回结果in result=task . end invoke(async result);控制台。WriteLine(结果);}以上代码的执行结果如下图所示。

因为是异步的,所以可能会在“任务开始”之前输出“*”,如上图所示。

五、使用WaitOne方法等待异步方法执行完成 使用WaitOne方法是判断异步调用是否完成的另一种方式。代码如下:

复制代码如下:static void main(string[]args){ newtaskdelegatetask=new task;IAsyncResult asyncResult=task。BeginInvoke(2000,null,null);

而(!异步结果。AsyncWaitHandle.WaitOne(100,false)) { Console。写(' * ');}

int结果=任务。EndInvoke(async result);控制台。WriteLine(结果);}

WaitOne的第一个参数指示等待的毫秒数。在指定的时间内,WaitOne方法将等待,直到异步调用完成并发出通知,WaitOne方法将返回true。等待指定时间后,异步调用仍未完成。WaitOne方法返回false。如果指定时间为0,则表示没有等待。如果为-1,则意味着永远等待,直到异步调用完成。

六、使用回调方式返回结果

以上方法其实只相当于一种方法。虽然这些方法可以成功返回结果,并给用户一些提示,但是在这个过程中,整个程序就像死了一样(如果读者在GUI程序中使用这些方法就会很明显)。如果程序在调用过程中还能正常做其他工作,就必须使用异步调用。让我们用GUI程序写一个例子。代码如下:

复制代码如下:私有委托int my method();private int方法(){ Thread。睡眠(10000);返回100;} private void method completed(IAsyncResult async result){ if(async result==null)返回;文本框1。Text=(asyncResult。AsyncState作为MyMethod)。EndInvoke(asyncResult)。ToString();}

私有void按钮1_Click(对象发送方,EventArgs e) {

MyMethod my=methodIAsyncResult asyncResult=my。BeginInvoke(MethodCompleted,my);}

注意,这里使用的是BeginInvoke方法的后两个参数(如果被调用的方法包含参数,这些参数将是BeginInvoke的第一部分参数;如果没有参数,BeginInvoke只有两个参数)。第一个参数是回调方法委托类型,它只有一个参数,即IAsyncResult,如MethodCompleted方法所示。当method方法完成后,系统会自动调用MethodCompleted方法。BeginInvoke的第二个参数需要传递一些值给MethodCompleted方法,一般可以传递被调用方法的委托,比如上面代码中的my。该值可以通过使用IAsyncResult获得。AsyncState属性。

由于上面的代码是以异步方式访问窗体上的一个textbox,所以需要按ctrl+f5才能运行程序(不能直接按F5运行程序,否则在其他线程中无法访问这个textbox。有关在其他线程中访问GUI组件的详细信息,请参考下一节)。并在窗体上放置一些其他可视控件。但是,点击button1后,其他控件仍然可以使用,就像什么都没发生一样。10秒钟后,textbox1中将输出100。

七。其他组件的BeginXXX和EndXXX方法

其他。net组件也有类似于BeginInvoke和EndInvoke的方法,比如系统的BeginGetResponse和EndGetResponse方法。HttpWebRequest类。下面是使用这两种方法的示例:

复制代码如下:private void请求完成(iasyncresult async result){ if(async result==null)返回;系统。net . http webrequest hwr=async result。AsyncState as系统。Net . HttpWebRequest系统。Net.HttpWebResponse响应=(系统。Net.HttpWebResponse)hwr。end getresponse(async result);系统。新系统。IO.StreamReader(响应。GetResponseStream());文本框1。text=Sr . ReadToEnd();}私人代表制度。net . http webresponse request delegate(System。Net.HttpWebRequest请求);

私有void按钮1_Click(对象发送方e) { System .网。HttpWebRequest请求=(系统. Net。HttpWebRequest)系统. net。网络请求。创建。jb51。net’);IAsyncResult asyncResult=请求BeginGetResponse(请求完成,请求);}

以上介绍的就是C#线程中贝京尼克和EndInvoke方法。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 设计一个简单的C#控制台应用程序,C#控制台程序,C# 创建控制台应用程序
  • 深入解析windows第8版,深入解析C#(第4版)
  • 数组代码,c# 数组操作,C# 数组实例介绍(图文)
  • 学会C#要多久,学会c#要多久,c#学习之30分钟学会XAML
  • 回溯法01背包问题c,回溯法求解01背包问题伪代码,C#使用回溯法解决背包问题实例分析
  • xml文件转义字符,xml转意字符,C# XML中的转义字符操作
  • winform 进度条控件,c# 进度条使用
  • winform 进度条控件,c# 进度条使用,C#使用winform实现进度条效果
  • winform backgroundworker,c# isbackground
  • winform backgroundworker,c# isbackground,C# BackgroundWorker用法详解
  • lua与c#交互,lua c#
  • lua与c#交互,lua c#,ToLua框架下C#与Lua代码的互调操作
  • linq c#,linq原理 c#
  • linq c#,linq原理 c#,c#中LINQ的基本用法实例
  • java decimal保留两位小数,sql中decimal函数保留2位小数,C#中decimal保留2位有效小数的实现方法
  • 留言与评论(共有 条评论)
       
    验证码: