One of the multithreading programming in. NET 4: using Task

Source: Internet
Author: User

 

To simplify multi-threaded programming,. NET 4 provides classes in the System. Threading. Tasks namespace to help developers with multi-threaded programming. The Task class is used to represent a thread. The simplest Task class accepts an Action delegate as the method to be executed, and calls the Start method to Start running in another thread. For example:

Using System;

Using System. Threading. Tasks;

Namespace TaskParallel

{

Class Program

{

Static void Main (string [] args)

{

Task task = new Task () => Console. WriteLine ("Write from another thread "));

Task. Start ();

Console. WriteLine ("Main Thread ");

Console. ReadLine ();

}

}

}

 

The order of the two outputs is not certain, but it is likely that:

Main Thread

Write from another thread

You can also use the Task. Factory. StartNew method. This method constructs a Task and starts running immediately. It is equivalent to connecting the constructor of the Task and the Start method for execution.

The Task class also has a constructor that can accept the Action <object> delegate and pass parameters to the Action:

Static void Main (string [] args)

{

For (int I = 0; I <5; I ++)

{

Task t = new Task (obj => Console. WriteLine ("Thread No" + obj), I );

T. Start ();

}

Console. ReadLine ();

}

The output result is similar:

Thread No 2

Thread No 1

Thread No 3

Thread No 0

Thread No 4

 

You can use the Task <T> class to obtain the returned value. T is the type of the returned value. For example:

Static void Main (string [] args)

{

Task <int> t = new Task <int> () =>

{

Int s = 0;

For (int I = 0; I <10000; I ++)

S + = I;

Return s;

});

T. Start ();

Console. WriteLine ("I'm computing ");

Console. WriteLine (t. Result );

Console. ReadLine ();

}

Result:

I'm computing

49995000

When you access t. Result,. net will ensure that the Task code has been executed and the Result has been obtained. Otherwise, the thread will block until the Result calculation is complete.

 

The Task library provides a method to actively terminate a thread. First, create a CancellationTokenSource, pass its Token attribute through the Task constructor, and round-robin The IsCancellationReqeusted attribute of the token within the Task, if true is detected, the thread is terminated. Call the Cancel Method of tokenSource in the parent thread to terminate the thread. Note: This is the method that the thread takes the initiative to terminate itself. The code in the Task must be terminated by itself, and. NET will not forcibly terminate the task thread, even if the parent thread calls the Cancel Method of tokenSource.

For example, if the following code does not have a break statement in the else statement block, the subthread will not terminate.

Using System;

Using System. Threading;

Using System. Threading. Tasks;

 

Namespace TaskParallel

{

Class Program

{

Static void Main (string [] args)

{

CancellationTokenSource tks = new CancellationTokenSource ();

CancellationToken token = tks. Token;

Long I = 0;

Task task = new Task () =>

{

While (true)

{

If (! Token. IsCancellationRequested)

I ++;

Else

{

Console. WriteLine ("Task is canceled, it looped" + I + "times ");

Break;

}

}

}, Token );

Task. Start ();

Console. WriteLine ("Press Enter to Cancel task ");

Console. ReadLine ();

Tks. Cancel ();

Console. ReadLine ();

}

}

}

You can also use the CancellationToken's Register Method to Register a delegate for the token. When the Cancel Method of tokenSource is called, the Delegate will be executed. This delegate is executed in the thread that calls the Cancel method.

Token. Register () =>{ Console. WriteLine ("Delegate Invoked ");});

 

To suspend the current thread and Wait for a thread to complete its execution, you can use the Wait () method of the execution thread. The Wait method has some overload methods that can specify the waiting time. For example:

Static void Main (string [] args)

{

Task t1 = new Task () =>

{

Console. WriteLine ("Task 1 Starts ...");

Thread. Sleep (3000 );

Console. WriteLine ("Task1 Ends ");

});

T1.Start ();

Task t2 = new Task () =>

{

Console. WriteLine ("Task2 Starts ...");

T1.Wait ();

Console. WriteLine ("Task2 Ends ");

});

Task t3 = new Task () =>

{

Console. WriteLine ("Task 3 is waiting Task1 for 1 second ...");

Bool finished = t1.Wait (1000 );

If (finished)

Console. WriteLine ("T1 is finished ");

Else

Console. WriteLine ("T1 is not finished ");

});

T2.Start ();

T3.Start ();

Console. ReadLine ();

}

The execution result is:

Task 1 Starts...

Task2 Starts...

Task 3 is waiting Task1 for 1 second...

T1 is not finished

Task1 Ends

Task2 Ends

You can use the Task. WaitAll method after multiple threads are executed,

Task t4 = new Task () =>

{

Console. WriteLine ("Waiting for all ");

Task. WaitAll (t1, t2, t3 );

Console. WriteLine ("Task4 Ends ");

});

T4.Start ();

There is also a Task. WaitAny, which can wait for any method in a group of threads to finish execution. The usage is similar.

 

The following describes how to handle exceptions in a Task. Generally, exceptions in a thread delegate will lead to thread termination, but exceptions will not be thrown. For example:

Task t = new Task () =>

{

Throw new Exception ();

Console. WriteLine ("Thread Ends ");

});

T. Start ();

Console. WriteLine ("Main Ends ");

The output is:

Main Ends

When Wait, WaitAll, WaitAny, Task. Result is called, AggerateException is thrown. In AggerateExcepiton, exceptions thrown by all threads can be handled:

Static void Main (string [] args)

{

Task t1 = new Task () =>

{

Throw new Exception ();

Console. WriteLine ("T1 Ends ");

});

 

Task t2 = new Task () =>

{

Throw new ArgumentException ();

Console. WriteLine ("T2 Ends ");

});

T1.Start ();

T2.Start ();

Try

{

Task. WaitAll (t1, t2 );

}

Catch (aggresponexception ex)

{

Foreach (var inner in ex. InnerExceptions)

{

Console. WriteLine (inner. GetType () + "" + inner. Source );

}

}

Console. WriteLine ("Main Ends ");

}

}

Sometimes some exceptions need to be treated differently. Some exceptions need to be thrown again. aggresponexception provides a Handle method to receive a Func <Exception, bool> delegate as a parameter, if you do not need to throw it again, true is returned; otherwise, false is returned.

Try

{

Task. WaitAll (t1, t2 );

}

Catch (aggresponexception ex)

{

Foreach (var inner in ex. InnerExceptions)

{

Console. WriteLine (inner. GetType () + "" + inner. Source );

}

Ex. Handle (e) =>

{

If (e is ArgumentException)

{

Console. WriteLine ("Argument Exception is captured ");

Return true;

}

Else

Return false;

});

}

In this way, unhandled exceptions will be thrown and aggresponexception will be thrown.

 


Author: yinzixin

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.