线程01:多线程之线程启动、参数、返回值
2011-02-10 14:57
344 查看
本章概要:
1:如何新起线程
2:Thread传参数及取得返回值
3:IsBackground
4:异步调用中的参数和返回值
创建多线程处理应用程序的最可靠方法是使用 BackgroundWorker 组件。但是,当你需要对线程进行精细控制的时候,就需要Thread。总体来说,各种方法各有各的优点,在这里不做细说。
大部分情况下,一个优良的写法是使用匿名函数,如下:
以上的写法,仍然无法解决返回值的问题。如果要获取返回值的,则使用委托或包裹类等其它方法。但以上方法解决了参数的问题。
首先,看代码:
代码段1:
在异步调用中,如果想在异步的回调函数中,得到异步函数的返回值(如上面代码中的Foo函数的string返回值),则必须要在回调函数中使用EndInvoke(关于EndInvoke会在下文描述)。在上面的例子是如下这句。
string re = fh.EndInvoke(ar);
但是,有的时候fh并不见得是个类变量,这个时候,就需要我们将EndInvoke的执行主体由BeginInvoke传递进去。看修改过后的代码片段。
代码段2:
通过举一反三,其实BeginInvoke的最后一个参数,可以是任何对象,看具体的应用场景即可。
下面再介绍一下EndInvoke。EndInvoke在回调函数中,用于承载执行的主体函数的返回值。在另外一个情况下,即上面的代码片段一个简化版本,如下:
代码段3:
我们可以看到,在这个代码片段中,我们根本没有使用回调函数,那么,我们就需要通过EndInvoke来阻滞主线程,使得返回函数主体的返回值。
再多说一点,调用了 BeginInvoke 后,可以:
1.进行某些操作,然后调用 EndInvoke 一直阻塞到调用完成。如上文的最后一个代码片段。
2.使用 IAsyncResult.AsyncWaitHandle 获取 WaitHandle,使用它的 WaitOne 方法将执行一直阻塞到发出 WaitHandle 信号,然后调用EndInvoke。这里主要是主程序等待异步方法,等待异步方法的结果。见代码段4。
3.轮询由 BeginInvoke 返回的 IAsyncResult,IAsyncResult.IsCompeted确定异步调用何时完成,然后调用 EndInvoke。
4.将用于回调方法的委托传递给 BeginInvoke。该方法在异步调用完成后在 ThreadPool 线程上执行,它可以调用 EndInvoke。这是在强制装换回调函数里面IAsyncResult.AsyncState(BeginInvoke方法的最后一个参数)成委托,然后用委托执行EndInvoke。即如上代码片段2。
代码段4:
参考:/article/4688972.html
练习:
1.You are developing an application to perform mathematical calculations. You develop a class named
CalculationValues. You write a procedure named PerformCalculation that operates on an instance of the class. You
need to ensure that the user interface of the application continues to respond while calculations are being
performed. You need to write a code segment that calls the PerformCalculation procedure to achieve this goal.
Which code segment should you use?
A. private void PerformCalculation() {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
Thread newThread = new Thread( new ThreadStart(PerformCalculation));
newThread.Start(myValues);}
B. private void PerformCalculation() {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
ThreadStart delStart = new ThreadStart(PerformCalculation);
Thread newThread = new Thread(delStart);
if (newThread.IsAlive) {newThread.Start(myValues);}}
C. private void PerformCalculation (CalculationValues values) {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
Application.DoEvents(); PerformCalculation(myValues);
Application.DoEvents();}
D. private void PerformCalculation(object values) {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
Thread newThread = new Thread( new ParameterizedThreadStart(PerformCalculation));
newThread.Start(myValues);}
Answer: D
2.You are developing an application that will perform mathematical calculations. You need to ensure that the
application is able to perform multiple calculations simultaneously. What should you do?
A. Set the IdealProcessor property of the ProcessThread object.
B. Set the ProcessorAffinity property of the ProcessThread object.
C. For each calculation, call the QueueUserWorkItem method of the ThreadPool class.
D. Set the Process.GetCurrentProcess().BasePriority property to High.
Answer: C
3.You are developing an application that will perform mathematical calculations. You need to ensure that the
application is able to perform multiple calculations simultaneously. What should you do?
A. Set the IdealProcessor property of the ProcessThread object.
B. Set the ProcessorAffinity property of the ProcessThread object.
C. For each calculation, call the QueueUserWorkItem method of the ThreadPool class.
D. Set the Process.GetCurrentProcess().BasePriority property to High.
Answer: C
4.Your application uses two threads, named threadOne and threadTwo. You need to modify the code to prevent the execution of threadOne until threadTwo completes execution.
What should you do?
A. Configure threadOne to run at a lower priority.
B. Configure threadTwo to run at a higher priority.
C. Use a WaitCallback delegate to synchronize the threads.
D. Call the Sleep method of threadOne.
E. Call the SpinLock method of threadOne.
Answer: C
转自:/article/4723270.html
1:如何新起线程
2:Thread传参数及取得返回值
3:IsBackground
4:异步调用中的参数和返回值
1:如何新起线程
新起一个线程的方法,可以使用Thread,BackgroundWorker ,ThreadPool,控件.BeginInvoke,委托.BeginInvoke,Timer。创建多线程处理应用程序的最可靠方法是使用 BackgroundWorker 组件。但是,当你需要对线程进行精细控制的时候,就需要Thread。总体来说,各种方法各有各的优点,在这里不做细说。
2:Thread传参数及取得返回值
Thread的有两个构造函数,其中一个使用参数是ThreadStart,说明该线程在构造函数中不能带入参数。还有一个ParameterizedThreadStart,则可以为你的线程传入参数。还有一个方法是为你的线程方法提供一个包裹类,这也可以解决返回值的问题。不过,这种方法在我看来是最丑陋的写法(参考http://msdn.microsoft.com/zh-cn/library/wkays279.aspx)。大部分情况下,一个优良的写法是使用匿名函数,如下:
int arg1 = 10; string arg2 = "argument temp"; Thread t1 = new Thread(new ThreadStart(delegate { MessageBox.Show(arg1.ToString() + arg2); }));
以上的写法,仍然无法解决返回值的问题。如果要获取返回值的,则使用委托或包裹类等其它方法。但以上方法解决了参数的问题。
3:IsBackground
必须注意IsBackground的问题,如果IsBackground为false的,则Windows程序在退出的时候,不会为你自动退出该线程。也就是实际上你的应用程序未结束。4:异步调用中的参数和返回值
能完美解决参数和返回值的是使用异步调用的方式。异步调用和Thread相比,一个最大的劣势是不能控制其优先级。首先,看代码:
代码段1:
public delegate string FuncHandle(int data1, int data2); FuncHandle fh ; private void BT_Temp_Click(object sender, RoutedEventArgs e) { fh = new FuncHandle(this.Foo); AsyncCallback callback = new AsyncCallback(this.AsyncCallbackImpl); fh.BeginInvoke(1, 3, callback, null); } public void AsyncCallbackImpl(IAsyncResult ar) { string re = fh.EndInvoke(ar); MessageBox.Show(" " + ar.AsyncState); } string Foo(int data1, int data2) { return " " + data1 + data2; }
在异步调用中,如果想在异步的回调函数中,得到异步函数的返回值(如上面代码中的Foo函数的string返回值),则必须要在回调函数中使用EndInvoke(关于EndInvoke会在下文描述)。在上面的例子是如下这句。
string re = fh.EndInvoke(ar);
但是,有的时候fh并不见得是个类变量,这个时候,就需要我们将EndInvoke的执行主体由BeginInvoke传递进去。看修改过后的代码片段。
代码段2:
public delegate string FuncHandle(int data1, int data2); private void BT_Temp_Click(object sender, RoutedEventArgs e) { FuncHandle fh = new FuncHandle(this.Foo); AsyncCallback callback = new AsyncCallback(this.AsyncCallbackImpl); fh.BeginInvoke(1, 3, callback, fh); } public void AsyncCallbackImpl(IAsyncResult ar) { FuncHandle dl = ar.AsyncState as FuncHandle; string re = dl.EndInvoke(ar); MessageBox.Show(" " + ar.AsyncState); } string Foo(int data1, int data2) { return "" + data1 + data2; }
通过举一反三,其实BeginInvoke的最后一个参数,可以是任何对象,看具体的应用场景即可。
下面再介绍一下EndInvoke。EndInvoke在回调函数中,用于承载执行的主体函数的返回值。在另外一个情况下,即上面的代码片段一个简化版本,如下:
代码段3:
public delegate string FuncHandle(int data1, int data2); private void BT_Temp_Click(object sender, RoutedEventArgs e) { FuncHandle fh = new FuncHandle(this.Foo); IAsyncResult ar = fh.BeginInvoke(1, 3, null, fh); string re = fh.EndInvoke(ar); MessageBox.Show(re); } string Foo(int data1, int data2) { return "" + data1 + data2; }
我们可以看到,在这个代码片段中,我们根本没有使用回调函数,那么,我们就需要通过EndInvoke来阻滞主线程,使得返回函数主体的返回值。
再多说一点,调用了 BeginInvoke 后,可以:
1.进行某些操作,然后调用 EndInvoke 一直阻塞到调用完成。如上文的最后一个代码片段。
2.使用 IAsyncResult.AsyncWaitHandle 获取 WaitHandle,使用它的 WaitOne 方法将执行一直阻塞到发出 WaitHandle 信号,然后调用EndInvoke。这里主要是主程序等待异步方法,等待异步方法的结果。见代码段4。
3.轮询由 BeginInvoke 返回的 IAsyncResult,IAsyncResult.IsCompeted确定异步调用何时完成,然后调用 EndInvoke。
4.将用于回调方法的委托传递给 BeginInvoke。该方法在异步调用完成后在 ThreadPool 线程上执行,它可以调用 EndInvoke。这是在强制装换回调函数里面IAsyncResult.AsyncState(BeginInvoke方法的最后一个参数)成委托,然后用委托执行EndInvoke。即如上代码片段2。
代码段4:
public delegate string FuncHandle(int data1, int data2); string _sTemp = string.Empty; private void BT_Temp_Click(object sender, RoutedEventArgs e) { FuncHandle fh = new FuncHandle(this.Foo); AsyncCallback callback = new AsyncCallback(this.AsyncCallbackImpl); IAsyncResult ar = fh.BeginInvoke(1, 3, null, null); WaitHandle waitHandle = ar.AsyncWaitHandle; waitHandle.WaitOne(); MessageBox.Show(_sTemp); } string Foo(int data1, int data2) { Thread.Sleep(3000); string re = "" + data1 + data2; _sTemp = re; return re; }
参考:/article/4688972.html
练习:
1.You are developing an application to perform mathematical calculations. You develop a class named
CalculationValues. You write a procedure named PerformCalculation that operates on an instance of the class. You
need to ensure that the user interface of the application continues to respond while calculations are being
performed. You need to write a code segment that calls the PerformCalculation procedure to achieve this goal.
Which code segment should you use?
A. private void PerformCalculation() {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
Thread newThread = new Thread( new ThreadStart(PerformCalculation));
newThread.Start(myValues);}
B. private void PerformCalculation() {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
ThreadStart delStart = new ThreadStart(PerformCalculation);
Thread newThread = new Thread(delStart);
if (newThread.IsAlive) {newThread.Start(myValues);}}
C. private void PerformCalculation (CalculationValues values) {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
Application.DoEvents(); PerformCalculation(myValues);
Application.DoEvents();}
D. private void PerformCalculation(object values) {...}
private void DoWork()
{ CalculationValues myValues = new CalculationValues();
Thread newThread = new Thread( new ParameterizedThreadStart(PerformCalculation));
newThread.Start(myValues);}
Answer: D
2.You are developing an application that will perform mathematical calculations. You need to ensure that the
application is able to perform multiple calculations simultaneously. What should you do?
A. Set the IdealProcessor property of the ProcessThread object.
B. Set the ProcessorAffinity property of the ProcessThread object.
C. For each calculation, call the QueueUserWorkItem method of the ThreadPool class.
D. Set the Process.GetCurrentProcess().BasePriority property to High.
Answer: C
3.You are developing an application that will perform mathematical calculations. You need to ensure that the
application is able to perform multiple calculations simultaneously. What should you do?
A. Set the IdealProcessor property of the ProcessThread object.
B. Set the ProcessorAffinity property of the ProcessThread object.
C. For each calculation, call the QueueUserWorkItem method of the ThreadPool class.
D. Set the Process.GetCurrentProcess().BasePriority property to High.
Answer: C
4.Your application uses two threads, named threadOne and threadTwo. You need to modify the code to prevent the execution of threadOne until threadTwo completes execution.
What should you do?
A. Configure threadOne to run at a lower priority.
B. Configure threadTwo to run at a higher priority.
C. Use a WaitCallback delegate to synchronize the threads.
D. Call the Sleep method of threadOne.
E. Call the SpinLock method of threadOne.
Answer: C
转自:/article/4723270.html
相关文章推荐
- C#笔记19:多线程之线程启动、参数、返回值
- C#笔记19:多线程之线程启动、参数、返回值
- C#笔记19:多线程之线程启动、参数、返回值
- [VB.NET]多线程——线程参数和返回值
- 第01天多线程网络:(01):进程和线程
- C++多线程框架(一)--------- new一下就启动一个线程
- (转)一步一步学习C#中的多线程 --- 1、初识线程(2)--给线程传递参数
- windows多线程编程-----1.四个线程同时输出//一个文件( 没有参数+有参数 )
- VB.NET多线程编程参数的传递以及返回值的获取
- android系统中的多线程(一): 关于在android中启动线程以及线程间的交互
- 1多线程的概述2多线程(创建多个线程实例,并启动多个线程)的实现方式,main主方法是单线程的4多线程的实现方式5多线程模拟火车站售票出现问题7线程的声明周期
- 【Java 语言】Java 多线程 一 ( 线程基础 : 线程启动 | 线程停止 | 线程暂停 | 线程优先级 | 守护线程)
- 01_张孝祥_Java多线程_传统线程技术回顾
- 多线程获取线程返回值---Future And CompletionService
- Java基础-多线程-①线程的创建和启动
- 多线程-2-线程创建与启动
- 多线程专题之线程参数
- 5.1多线程使用(不带参数的构造函数进行定义多线程)
- paip.java 多线程参数以及返回值Future FutureTask 的使用.
- C#向线程传递参数和获得返回值