c#invoke方法作用,c# BeginInvoke,C# Invoke,begininvoke的用法详解

c#invoke方法作用,c# BeginInvoke,C# Invoke,begininvoke的用法详解

本文主要介绍C#调用begininvoke的用法,帮助大家更好的理解和使用c#。感兴趣的朋友可以了解一下。

invoke和begininvoke的用法和概念一直令人困惑。这两天看了一些资料,对它们的用法和原理有了一些新的认识和理解。

首先,invoke和begininvoke用于两种情况:

1.invoke,开始控制invoke。

2.调用,在删除中开始调用。

这两种情况是不一样的,这里要说的是第一种。让我们来谈谈invoke和begininvoke的官方定义。网。

Control.invoke(参数委托)方法:在拥有此控件的基础窗口句柄的线程上执行指定的委托。

Control.begininvoke(参数委托)方法:在创建控件基础句柄的线程上异步执行指定的委托。

根据这两个概念,我们可以大致理解invoke表是同步的,begininvoke是异步的意思。

如果您的后台线程在更新UI控件的状态后不需要等待,而是继续处理它,那么您应该使用BeginInvoke进行异步处理。

如果您的后台线程需要操作UI控件,并且需要等到操作完成后才能继续,那么您应该使用Invoke。

让我们做一个测试。

invoke例子:

私有void button1_Click(对象发送方,EventArgs e)

{

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()' AAA ');

invoke Thread=new Thread(new ThreadStart(start method));

invokeThread。start();

字符串a=字符串。空的;

for(int I=0;i3;I) //调整循环数,看得更清楚。

{

线程。睡眠(1000);

a=a‘B’;

}

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()a);

}

私有void StartMethod()

{

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()' CCC ');

按钮1。Invoke(新的invoke delegate(invoke method));

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()“DDD”);

}

私有void invokeMethod()

{

//线程。睡眠(3000);

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()“EEE”);

}

结论:我们运行后,看看程序的运行顺序,1AAA-3CCC,1BBB-1EEE -3DDD。

解释:主线程运行1AAA,然后1BBB和子线程3CCC同时执行,然后通过invoke向主线程提交invoke方法,然后子线程等待主线程执行Invoke方法,直到主线程完成执行(Invoke提交的任务只有在主线程完成执行后才会执行),最后执行子线程3DDD。

begininvoke例子:

私有void button1_Click(对象发送方,EventArgs e)

{

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()' AAA ');

invoke Thread=new Thread(new ThreadStart(start method));

invokeThread。start();

字符串a=字符串。空的;

for(int I=0;i3;I) //调整循环数,看得更清楚。

{

线程。睡眠(1000);

a=a‘B’;

}

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()a);

}

私有void StartMethod()

{

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()' CCC ');

按钮1。BeginInvoke(新的invoke delegate(invoke method));

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()“DDD”);

}

私有void beginInvokeMethod()

{

//线程。睡眠(3000);

MessageBox。显示(线程。CurrentThread.GetHashCode()。ToString()' EEEEEEEEEEEE ');

}

结论:我们来看看运行后的执行结果:1AAA-1BBB和3CCC-1EEE和3DDD。

解释:主线程运行1AAA,然后1BBB和子线程3CCC同时执行,然后通过begininvoke向主线程提交invokemethod方法,然后主线程执行1EEE(主线程自己的任务完成),子线程继续执行3DDD。

通过对两个代码的测试对比,我们会发现,invoke和begininvoke提交的委托方法实际上是在主线程中执行的。其实按照我对invoke和begininvoke的定义,我们要在子线程里看这个问题。在invoke例子中,我们会发现DDD;在执行invoke提交的委托方法之前,无法继续。在begininvoke的例子中,我们会发现在begininvoke提交委托方法后,子线程会继续执行DDD,而不会等待委托方法的完成。现在让我们回忆一下invoke(同步)和begininvoke(异步)的概念。实际上,它们的意思是相对于子线程的。事实上,对控件的调用总是由主线程执行。我们许多人对同步和异步感到困惑,主要是因为我们选择了错误的参考。其实有时候光看概念就很容易理解错误。

解决从不是创建控件的线程访问控件的问题。

在多线程编程中,我们经常需要在工作线程中更新界面显示,但是在多线程中直接调用界面控件是错误的。Invoke和BeginInvoke的出现解决了这个问题,让你可以在多线程中安全的更新界面显示。

正确的做法是将worker线程中更新接口所涉及的代码封装到一个方法中,通过Invoke或BeginInvoke调用。两者的区别在于,一个会导致工作线程等待,而另一个则不会。

所谓的“一边响应操作一边添加节点”永远只能是相对的,这样UI线程的负担才不会太大。因为界面的正确更新总是需要通过UI线程来完成,我们需要做的就是在工作线程中完成大部分操作,把纯界面更新放到UI线程中去做,从而达到减轻UI线程负担的目的。

举一个简单的例子来说明如何使用这个方法。例如,您正在启动一个线程,并且希望在thread方法中更新表单中的TextBox。

使用系统。穿线;

//启动一个线程

Thread Thread=new Thread(new ThreadStart(DoWork));

线程。start();

//线程方法

私有void DoWork()

{

这个。TextBox1.Text='我是文本框';

}

如果按上述操作,VS2005或2008中会有例外。

正确的做法是用Invoke\BeginInvoke

使用系统。穿线;

名称空间测试

{

公共分部类Form1 : Form

{

公共委托void MyInvoke(字符串str1,字符串str 2);

公共表单1()

{

initialize component();

}

public void DoWork()

{

my invoke mi=new my invoke(update form);

This.begininvoke (mi,newobject [] { '我是文本框','哈哈' });

}

public void update form(string param 1,string parm2)

{

this . textbox 1 . text=param 1 parm 2;

}

私有void button1_Click(对象发送方,EventArgs e)

{

Thread Thread=new Thread(new ThreadStart(DoWork));

线程。start();

}

}

}

注意药剂的使用!

以后再补充。

WinForm开发中经常用到线程,有时需要在线程中访问线程外的控件,比如设置textbox的Text属性等等。如果直接安装程序必须报告没有创建控件的线程访问它,则此异常。通常情况下,我们可以通过两种方式来解决。首先,通过设置控件的属性。第二,通过委托,通过委托有两种方式,一种是常用的,另一种是匿名的。下面分别解释。

首先,通过将control的一个属性值设置为false。我们可以在Form_Load方法中添加:control . checkforillegalcrosthreadcalls=false;来解决。设置为false表示不会捕获错误线程的调用。这样,在线程中设置textbox的Text属性时就不会报错。

其次,用委托的方法解决。

常见的委托方法,如:

委托void SafeSetText(字符串strMsg);

私有void SetText(字符串strMsg)

{

if(textbox1。需要发票)

{

safe SetText objSet=new safe SetText(SetText);

文本框1。Invoke(objSet,new object[]{ strMsg });

}

其他

{

文本框1。Text=strMsg

}

}

当需要在线程中设置textbox的值时,可以调用SetText方法。我们还可以通过另一种委托方式来实现,即匿名代理,例如:

委托void SafeSetText(字符串strMsg);

私有void SetText2(字符串strMsg)

{

SafeSetText objSet=delegate(string字符串)

{

文本框1。Text=str

}

文本框1。Invoke(objSet,new object[]{ strMsg });

}

这也可以实现。

个人觉得还是用代理比较好。

在C# 3.0和更高的版本中,Lamda expression使得上面的匿名委托写得更加简洁。的。NET Framework3.5版及更高版本可以更好地用Action封装方法。例如,下面的措辞可能看起来非常简洁:

void ButtonOnClick(对象发送方,事件参数e)

{

这个。调用(新操作(()=

{

按钮。Text=' close

}));

}

最新:

调用(()=

{

按钮。Text=' close

});

这就是C# Invoke的使用细节,begininvoke。更多关于C# Invoke,begininvoke的信息,请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行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位有效小数的实现方法
  • 留言与评论(共有 条评论)
       
    验证码: