委托和线程

一:线程
在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。
不带参数的启动方式
 如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread:
 带参数的启动方法

带参数 ,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要 ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同 的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。 为 什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接 口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类) 等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在启动方法中进行相应的类型转换。
这种object类型的参数可以定义一个有多个属性的类来进行,或者用$隔开的字符串,使用的时候分解为数组来用
简单实例代码:
<span class="com">//不带参数</span><span class="pln">
</span><span class="typ">ThreadStart</span><span class="pln"> ts </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ThreadStart</span><span class="pun">(</span><span class="typ">ThreadFunc</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Thread</span><span class="pln"> t </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">(</span><span class="pln">ts</span><span class="pun">);</span><span class="pln">
t</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">

</span><span class="com">//带参数 </span><span class="pln">
</span><span class="typ">ParameterizedThreadStart</span><span class="pln"> </span><span class="typ">ParStart</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ParameterizedThreadStart</span><span class="pun">(</span><span class="typ">GoTo</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Thread</span><span class="pln"> myThread </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">(</span><span class="typ">ParStart</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">object</span><span class="pln"> o </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">object</span><span class="pun">)</span><span class="pln">txt_url</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">;</span><span class="pln">
myThread</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">(</span><span class="pln">o</span><span class="pun">);</span>
详细实例代码:
<span class="typ">Program</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Program</span><span class="pun">();</span><span class="pln">
 </span><span class="typ">Thread</span><span class="pln"> nonParameterThread </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ThreadStart</span><span class="pun">(</span><span class="pln">p</span><span class="pun">.</span><span class="typ">NonParameterRun</span><span class="pun">));</span><span class="pln">
 nonParameterThread</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">

 </span><span class="typ">Thread</span><span class="pln"> parameterThread </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ParameterizedThreadStart</span><span class="pun">(</span><span class="pln">p</span><span class="pun">.</span><span class="typ">ParameterRun</span><span class="pun">));</span><span class="pln">
 parameterThread</span><span class="pun">.</span><span class="typ">Name</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Thread A:"</span><span class="pun">;</span><span class="pln">
 parameterThread</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">(</span><span class="lit">30</span><span class="pun">);</span><span class="pln">
                
                 </span><span class="com">/// <summary></span><span class="pln">
                 </span><span class="com">/// 不带参数的启动方法</span><span class="pln">
                 </span><span class="com">/// </summary></span><span class="pln">
                 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">NonParameterRun</span><span class="pun">()</span><span class="pln">
                 </span><span class="pun">{</span><span class="pln">
                         </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
                         </span><span class="pun">{</span><span class="pln">
                                 </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"系统当前时间毫秒值:"</span><span class="pun">+</span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">.</span><span class="typ">Millisecond</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">());</span><span class="pln">
                                 </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="lit">200</span><span class="pun">);</span><span class="com">//让线程暂停</span><span class="pln">
                         </span><span class="pun">}</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                </span><span class="com">/// <summary></span><span class="pln">
                 </span><span class="com">/// 带参数的启动方法</span><span class="pln">
                 </span><span class="com">/// </summary></span><span class="pln">
                 </span><span class="com">/// <param name="ms">让线程在运行过程中的休眠间隔</param></span><span class="pln">
                 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ParameterRun</span><span class="pun">(</span><span class="kwd">object</span><span class="pln"> ms</span><span class="pun">)</span><span class="pln">
                 </span><span class="pun">{</span><span class="pln">
                         </span><span class="kwd">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
                         </span><span class="kwd">int</span><span class="pun">.</span><span class="typ">TryParse</span><span class="pun">(</span><span class="pln">ms</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(),</span><span class="pln"> </span><span class="kwd">out</span><span class="pln"> j</span><span class="pun">);</span><span class="com">//这里采用了TryParse方法,避免不能转换时出现异常</span><span class="pln">
                         </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
                         </span><span class="pun">{</span><span class="pln">
                                 </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">CurrentThread</span><span class="pun">.</span><span class="typ">Name</span><span class="pun">+</span><span class="str">"系统当前时间毫秒值:"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">.</span><span class="typ">Millisecond</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">());</span><span class="pln">
                                 </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="pln">j</span><span class="pun">);</span><span class="com">//让线程暂停</span><span class="pln">
                         </span><span class="pun">}</span><span class="pln">
                 </span><span class="pun">}</span>
二:委托
委托就是讲方法以参数的形式进行传递
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">WriteStrToFile</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> txt</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
write</span><span class="pun">(</span><span class="pln">txt</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">delegate</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">WriteStrToFileDelegate</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> txt</span><span class="pun">);</span><span class="com">//定义委托</span><span class="pln">
</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WriteStrToFileDelegate</span><span class="pun">(</span><span class="typ">WriteStrToFile</span><span class="pun">).</span><span class="typ">BeginInvoke</span><span class="pun">(</span><span class="pln">txt</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">);</span><span class="com">//异步使用委托</span>
再举一例:
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">delegate</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">GreetingDelegate</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> name</span><span class="pun">);</span><span class="com">//定义委托</span><span class="pln">

</span><span class="com">//定义两方法</span><span class="pln">
</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">EnglishGreeting</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> name</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
 </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Morning, "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> name</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ChineseGreeting</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
 </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"早上好, "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> name</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span>
使用:
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">GreetPeople</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> </span><span class="typ">GreetingDelegate</span><span class="pln"> </span><span class="typ">MakeGreeting</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
  </span><span class="typ">MakeGreeting</span><span class="pun">(</span><span class="pln">name</span><span class="pun">);</span><span class="com">//这里默认同步方式,与MakeGreeting.Invoke(name)效果一样</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">//使用</span><span class="pln">
</span><span class="typ">GreetPeople</span><span class="pun">(</span><span class="str">"Jimmy Zhang"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">EnglishGreeting</span><span class="pun">);</span><span class="pln">
</span><span class="typ">GreetPeople</span><span class="pun">(</span><span class="str">"张子阳"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ChineseGreeting</span><span class="pun">);</span>
实际上,我们可以也可以绕过GreetPeople方法,通过委托来直接调用EnglishGreeting和ChineseGreeting: 
<span class="typ">GreetingDelegate</span><span class="pln"> delegate1</span><span class="pun">;</span><span class="pln">
  delegate1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">EnglishGreeting</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 先给委托类型的变量赋值</span><span class="pln">
  delegate1 </span><span class="pun">+=</span><span class="pln"> </span><span class="typ">ChineseGreeting</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 给此委托变量再绑定一个方法</span><span class="pln">
  </span><span class="com">// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法</span><span class="pln">
  delegate1 </span><span class="pun">(</span><span class="str">"Jimmy Zhang"</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln"> </span>

委托的 Invoke 方法用来进行 同步调用 。同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行。同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕的用户体验,这时候异步调用就很有必要了。
异步调用 不阻塞线程,而是把调用塞到线程池中,程序主线程或UI线程可以继续执行。
委托的异步调用通过 BeginInvoke EndInvoke 来实现。

比较:

在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。

委托其实也是一个线程


<span class="typ">MethodInvoker</span><span class="pln"> mi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MethodInvoker</span><span class="pun">(</span><span class="typ">DoPay</span><span class="pun">);</span><span class="com">//定义委托</span><span class="pln">
            </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">BeginInvoke</span><span class="pun">(</span><span class="pln">mi</span><span class="pun">);</span>


这里MethodInvoker 
只是一个委托, 我们可以认为所有没有参数的返回值为void的委托和 MethodInvoker 是一样的, 他们都可以委托到没有参数的返回值为void的方法。

你自己写一个 Public Delegate Sub ABC, 这个时候ABC和MethodInvoker是完全一样的。所以.Net 提供这个只是为了方便你编写,省得你自己再写一堆一样的委托了。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C#中,委托和多线程是常用的处理并发编程的方法。委托是一种类型,它可以存储对一个或多个方法的引用,并允许在需要时调用这些方法。通过使用委托,我们可以在不同的线程中执行不同的方法。\[2\] 在C#中,线程是使用Thread类处理的。可以通过创建Thread对象并传递一个方法作为参数来创建线程。例如,可以使用Thread类的构造函数创建一个新的线程,并将一个方法作为参数传递给它。然后,可以调用Start方法来启动线程的执行。\[1\] 然而,在使用多线程时,需要注意跨线程访问控件的问题。一般情况下,窗体的控件是属于主线程的,如果在其他线程中直接访问控件,会导致报错。为了解决这个问题,可以使用委托来在其他线程中更新控件的值。首先,需要声明一个委托类型,然后创建一个委托对象,并将要执行的方法作为参数传递给它。接下来,可以创建一个新的线程,并在该线程中调用Invoke方法来更新控件的值。\[2\] 另外,C#还提供了使用Task类来创建多线程的方法。可以使用Task.Factory.StartNew方法来创建一个新的任务,并传递一个方法作为参数。然后,可以使用Task.WaitAll方法等待所有任务执行完成,或者使用Task.WaitAny方法等待任意一个任务执行完成。\[3\] 总结起来,委托和多线程是C#中处理并发编程的常用方法。委托可以用于在不同的线程中执行不同的方法,而多线程可以通过Thread类或Task类来创建和管理线程。在使用多线程时,需要注意跨线程访问控件的问题,并可以使用委托来解决这个问题。 #### 引用[.reference_title] - *1* *2* *3* [c#多线程委托的使用](https://blog.csdn.net/qq_39559182/article/details/103954877)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值