线程,任务,并发编程
异步委托
异步调用有返回值的委托和没返回值的委托。
异步调用无返回值的委托
PrintSomething printFruit = (d) =>
{
Thread.Sleep(3000);
Console.WriteLine("\n\ryou input this fruit:"+d);
};
IAsyncResult result = printFruit.BeginInvoke("orange", null, null);
Console.Write("Longing");
while (!result.IsCompleted)
{
Console.Write(".");
Thread.Sleep(100);
}
执行结果
Longing............................... you input this fruit:orange |
异步调用有返回值的委托
//异步调用有返回值的委托
getSum factorial = (i) =>
{
Thread.Sleep(5000);
int tmp = 1;
for (int index = 1; index <= i; index++)
{
tmp *= index;
}
return tmp;
};
//这个调用添加了回调函数
IAsyncResult result = factorial.BeginInvoke(10, (d) => {
getSum tmp = d.AsyncState as getSum;
Trace.Assert(tmp != null, "回调参数转换失败");
Console.WriteLine(
string.Format("\nfinished.this result is:{0}"
,tmp.EndInvoke(d)));
}, factorial); //factorial.beginInvoke
Console.Write("Computing");
while (!result.IsCompleted)
{
Console.Write(".");
//Thread.Sleep(100);
result.AsyncWaitHandle.WaitOne(100);
}
//如果不添加回调函数就用这个
// Console.WriteLine(
string.Format("\nresult is {0}"
, factorial.EndInvoke(result)));
执行结果
Computing................................................... finished.this result is:3628800 |
给线程传递参数
很多时候我们生成的线程需要根据参数来工作,这时候就要给他们传递参数了。给线程传递参数必须保证在线程的声明周期内参数的可访问性。有两种比较常用的方法给线程传递参数,他们分别为:
方法一:
Thread myThread = new Thread((data1) => {
Hashtable table = data1 as Hashtable;
foreach (string k in table.Keys)
{
Console.WriteLine(table[k]);
}
});
Hashtable myTable = new Hashtable();
myTable["1"] = "data1";
myTable["2"] = "data2";
myTable["3"] = "data3";
myTable["4"] = "data4";
myTable["5"] = "data5";
myThread.Start(myTable);
执行结果:
data1 data2 data3 data4 data5 |
方法二:
MyClass myClass = new MyClass();
myClass.Data = "Bomb";
Thread myThread = new Thread(myClass.PrintSomething);
myThread.Start();
public class MyClass {
public string Data { get; set; }
public void PrintSomething() {
Console.WriteLine("this data is:" + Data);
}
执行结果:
this data is:Bomb |
线程调度
一些线程的常用方法:挂起,中断,激活。
Thread bgThread=new Thread(
()=>{
Thread.Sleep(3000);
Console.WriteLine("\nFinished!");
});
bgThread.IsBackground = false;//设置线程是否为后台线程
bgThread.Start();//开始
Console.WriteLine(
string.Format("The thread state is:{0}"
, bgThread.ThreadState));
bgThread.Suspend();//挂起
Console.WriteLine(
string.Format("The thread state is:{0}"
, bgThread.ThreadState));
Console.WriteLine("Do you want to continue the thead? Y/N");
ConsoleKeyInfo input = Console.ReadKey();
if (input.KeyChar.toString().toUpper() == “Y”)
{
bgThread.Resume(); //继续
}
Console.WriteLine("Do you want to stop the thead? Y/N");
input = Console.ReadKey();
if (input.KeyChar.toString().toUpper() == “Y”)
{
bgThread.Abort(); //取消
}
bgThread.Join();//阻塞当前线程,直到线程bgThread执行完毕
通过线程运行的优先级别来进行调度
Thread thread1 = new Thread(
() => {
Thread.Sleep(5000);
Console.WriteLine("thread1");
});
Thread thread2 = new Thread(
() => { Thread.Sleep(5000);
Console.WriteLine("thread2");
});
Thread thread3 = new Thread(
() => {
Thread.Sleep(5000);
Console.WriteLine("thread3");
});
Thread thread4 = new Thread(
() => {
Thread.Sleep(5000);
Console.WriteLine("thread4");
});
Thread thread5 = new Thread(
() => {
Thread.Sleep(5000);
Console.WriteLine("thread5");
});
thread1.Priority = ThreadPriority.Lowest;
thread2.Priority = ThreadPriority.BelowNormal;
thread3.Priority = ThreadPriority.Normal;
thread4.Priority = ThreadPriority.AboveNormal;
thread5.Priority = ThreadPriority.Highest;
thread1.Start();
thread2.Start();
thread3.Start();
thread4.Start();
thread5.Start();
执行结果:
thread2 thread3 thread4 thread5 thread1
|
线程池
都叫“池”了,当然是为了提高系统的性能,去除频繁实例化线程的额外开销。
//线程池
int workerThreads, completionPortThreads;
ThreadPool.GetMaxThreads(
out workerThreads
, out completionPortThreads);
Console.WriteLine(
string.Format("WorkerThread Num:{0}
,CompletionPortThreads Num:{1}"
, workerThreads
, completionPortThreads));
//var testMethod = () => Console.WriteLine("ok");
for (int i = 1; i < 20; i++)
{
ThreadPool.QueueUserWorkItem(
(o) => {
Console.WriteLine("Current Thread Id:{0}"
, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(100); });//writeline
}//for
执行结果:
WorkerThread Num:1023,CompletionPortThreads Num:1000 Current Thread Id:7 Current Thread Id:12 Current Thread Id:11 Current Thread Id:13 Current Thread Id:7 Current Thread Id:12 Current Thread Id:11 Current Thread Id:13 Current Thread Id:7 Current Thread Id:11 Current Thread Id:12 Current Thread Id:13 Current Thread Id:7 Current Thread Id:12 Current Thread Id:11 Current Thread Id:7 Current Thread Id:13 Current Thread Id:12 Current Thread Id:11 |
任务
感觉和线程差不多,只是添加了更多的可控性。比如:可以按照一定的逻辑连续运行;根据上一任务的运行情况来执行相应的任务。
TaskFactory taskFactory = new TaskFactory();
Task myTask1 = taskFactory.StartNew(
() => Console.WriteLine("Hello Task1")
);
Task myTask2 = Task.Factory.StartNew(
() => Console.WriteLine("Hello Task2")
);
Task myTask3 = new Task(
() => Console.WriteLine("Hello Task3")
);
myTask3.Start();
执行结果:
Hello Task1 Hello Task2 Hello Task3 |
连续执行任务(包含出错处理):
//连续执行任务
Task task1 = new Task(
() => {
Thread.Sleep(1000);
Console.WriteLine(DateTime.Now.ToString("ss"));
});
Task task2 = task1.ContinueWith(
(t) => {
Thread.Sleep(1000);
Console.WriteLine(DateTime.Now.ToString("ss"));
});
Task task3 = task2.ContinueWith(
(t) => {
Thread.Sleep(1000);
Console.WriteLine(DateTime.Now.ToString("ss"));
});
Task task4 = task3.ContinueWith(
(t) => {
Thread.Sleep(1000);
Console.WriteLine(DateTime.Now.ToString("ss"));
throw new Exception("error");
});
//当任务出错了执行
Task task5 = task4.ContinueWith(
(t) => Console.WriteLine("之前的任务出了错")
, TaskContinuationOptions.OnlyOnFaulted);
task1.Start();
执行结果:
45 46 47 48 之前的任务出了错 |
有返回值的任务:
var myTask = new Task<int>(() => 1);
myTask.Start();
Console.WriteLine(string.Format("The result is:{0}", myTask.Result));
myTask.Wait(-1);
执行结果:
The result is:1 |
并行编程
.Net4中添加了2个并行编程的方法:for和foreach。通过使用这两个方法体可以简单的使用并行技术来编程程序。
//并行编程
Parallel.For(
0
,10
, (index) => Console.WriteLine("current task is:"
+ index.ToString()));
执行结果:
current task is:0 current task is:2 current task is:1 current task is:3 current task is:4 current task is:6 current task is:8 current task is:5 current task is:9 current task is:7
|
并行编程(For)
Parallel.For(1, 20,
(index, state) =>
{
if (index % 2 == 0)
{
//state.Break();//终止并发操作
Console.WriteLine(
string.Format("{0}:Current task id:{1}"
, index
, Thread.CurrentThread.ManagedThreadId));
}//if
});//paraller.for
执行结果:
2:Current task id:10 4:Current task id:10 10:Current task id:11 6:Current task id:10 12:Current task id:11 14:Current task id:12 8:Current task id:10 18:Current task id:12 16:Current task id:11 |
//第一个委托参数:执行任务的线程开始运行时触发
//第二个委托参数:执行迭代任务的委托
//第三个委托参数:执行任务的线程结束运行时触发
Parallel.For<string>(1
,
20
, () =>
{
Console.WriteLine(string.Format("Thread:{0} is working!",
Thread.CurrentThread.ManagedThreadId));
return Thread.CurrentThread.ManagedThreadId.ToString();
}//第一个委托参数
,
(index, state, head) =>
{
Thread.Sleep(100);
Console.WriteLine(
string.Format("Current Thread is {0}
,Current Loop index is {1}"
, head
, index));
return head;
}//第二个委托参数
,
(data) => Console.WriteLine(string.Format("thread:{0} is finished!", data))
);//For
执行结果:
Thread:8 is working! Thread:9 is working! Thread:10 is working! Thread:11 is working! Current Thread is 8,Current Loop index is 1 Thread:12 is working! Current Thread is 9,Current Loop index is 5 Current Thread is 10,Current Loop index is 9 Current Thread is 11,Current Loop index is 13 Current Thread is 8,Current Loop index is 2 Current Thread is 12,Current Loop index is 17 Current Thread is 9,Current Loop index is 6 Current Thread is 10,Current Loop index is 10 Current Thread is 11,Current Loop index is 14 Current Thread is 8,Current Loop index is 3 Current Thread is 12,Current Loop index is 18 Current Thread is 9,Current Loop index is 7 thread:9 is finished! Current Thread is 10,Current Loop index is 11 Thread:9 is working! thread:10 is finished! Current Thread is 8,Current Loop index is 4 Current Thread is 11,Current Loop index is 15 Current Thread is 12,Current Loop index is 19 Thread:10 is working! thread:11 is finished! thread:12 is finished! Current Thread is 9,Current Loop index is 8 thread:9 is finished! Current Thread is 8,Current Loop index is 16 Current Thread is 10,Current Loop index is 12 thread:8 is finished! thread:10 is finished!
|
ForEach方法:
//Parallel.ForEach方法
string[] fruit = new string[] { "Orange"
, "Banana"
, "Apple"
, "Pear"
, "Grape"
, "Watermelon"
, "Pineapple"
, "Coconut"
, "Kiwifruit"
, "Lemon" };
Parallel.ForEach<string>(fruit, (data) => { Thread.Sleep(1000); Console.WriteLine(data); });
Parallel.ForEach<string>(fruit, (data, state, index) =>
{
Console.WriteLine(string.Format("{0}:{1}", index, data));
});
执行结果:
Orange Apple Grape Kiwifruit Pineapple Banana Watermelon Pear Lemon Coconut 0:Orange 2:Apple 4:Grape 3:Pear 1:Banana 6:Pineapple 5:Watermelon 8:Kiwifruit 7:Coconut 9:Lemon |
并发调用委托
//并发调用多个委托
Parallel.Invoke( () => Console.WriteLine("1")
, () => Console.WriteLine("2")
, () => Console.WriteLine("3")
, () => Console.WriteLine("4")
, () => Console.WriteLine("5")
, () => Console.WriteLine("6")
, () => Console.WriteLine("7")
, () => Console.WriteLine("8")
, () => Console.WriteLine("9")
, () => Console.WriteLine("10")
);
并发编程,根据逻辑取消任务的执行
//并发编程中的任务取消操作
//简介:该例子会在下面这个Parallel.For方法体开始执行100毫秒后终止它。
var cancel = new CancellationTokenSource();
cancel.Token.Register(
()=>string.Format("Thread:{0} was canceled!"
,Thread.CurrentThread.ManagedThreadId));
new Task(() =>
{
Thread.Sleep(100);
cancel.Cancel();
Console.WriteLine("Operation was canceled!");
}).Start();
try
{
ParallelLoopResult result = Parallel.For(0
, 100
, new ParallelOptions()
{
CancellationToken = cancel.Token
}
, (x) =>
{
Console.WriteLine(x);
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
执行结果:
0 1 2 3 25 4 26 27 50 5 Operation was canceled! 已取消该操作。 |
取消正在执行的任务
当需要根据程序的环境来决定正在执行的并发任务是否要继续执行时,可以用这段代码来解决。
//取消正在执行的Task
var cancel = new CancellationTokenSource();
cancel.Token.Register(
()=>Console.WriteLine("Operation was cancel")
);
new Task(() =>
{
Thread.Sleep(100);
cancel.Cancel();
}).Start();
TaskFactory taskFactory = new TaskFactory(cancel.Token);
Task myTask= taskFactory.StartNew(
new Action<object>(
(f) =>
{
for (int i = 1; i <= 100; i++)
{
CancellationToken token = (f as TaskFactory).CancellationToken;
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
break;
}
Console.WriteLine(string.Format("Current Loop index is {0}", i));
Thread.Sleep(20);
}
}
),taskFactory,cancel.Token);
try
{
myTask.Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
执行结果:
Current Loop index is 1 Current Loop index is 2 Current Loop index is 3 Operation was cancel 发生一个或多个错误。 |
Barieer(对数据分块进行处理)
class MyBarrier
{
public static IEnumerable<string> FillData(int size)
{
List<string> data = new List<string>(size);
Random r = new Random();
for (int i = 0; i < size; i++)
{
data.Add(GetString(r));
}
return data;
}
//返回长度为6的小写字母
public static string GetString(Random r)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 6; i++)
{
sb.Append((char)(r.Next(26) + 97));
}
return sb.ToString();
}
public static int[] CalculationInTask(object p)
{
var p1 = p as Tuple<int, int, Barrier, List<string>>;
Barrier barrier = p1.Item3;
List<string> data = p1.Item4;
int start = p1.Item1 * p1.Item2;
int end = start + p1.Item2;
Console.WriteLine("Task {0}:partition from {1} to {2}",Task.CurrentId,start,end);
int[] charCount = new int[26];
for (int j = start; j < end; j++)
{
char c = data[j][0];
charCount[c - 97]++;
}
Console.WriteLine("Calculation completed from task {0}.{1} times a,{2} times z", Task.CurrentId, charCount[0], charCount[25]);
barrier.RemoveParticipant();
Console.WriteLine("Task {0} removed from barrier,remaining participants {1}", Task.CurrentId, barrier.ParticipantsRemaining);
return charCount;
}
public static void Go()
{
const int numberTasks = 2;
const int partitionSize = 1000000;
var data = new List<string>(FillData(partitionSize * numberTasks));
var barrier = new Barrier(numberTasks + 1);
var taskFactory = new TaskFactory();
var tasks = new Task<int[]>[numberTasks];
for (int i = 0; i < numberTasks; i++)
{
tasks[i] = taskFactory.StartNew<int[]>(CalculationInTask,
Tuple.Create(i, partitionSize, barrier, data));
}
barrier.SignalAndWait();
var resultCollection = tasks[0].Result.Zip(tasks[1].Result, (c1, c2) =>
{
return c1 + c2;
});
char ch = 'a';
int sum = 0;
foreach (var x in resultCollection)
{
Console.WriteLine("{0}, count: {1}", ch++, x);
sum += x;
}
Console.WriteLine("main finished {0}", sum);
Console.WriteLine("remaining {0}, phase {1}", barrier.ParticipantsRemaining, barrier.CurrentPhaseNumber);
}
}
调用代码:
/Barrier类
MyBarrier.Go();//传说可以将任务进行分块处理的类
执行结果:
Task 1:partition from 0 to 1000000 Task 2:partition from 1000000 to 2000000 Calculation completed from task 1.38040 times a,38365 times z Task 1 removed from barrier,remaining participants 1 Calculation completed from task 2.38621 times a,38212 times z Task 2 removed from barrier,remaining participants 1 a, count: 76661 b, count: 77683 c, count: 77014 d, count: 77177 e, count: 76848 f, count: 77223 g, count: 77168 h, count: 77175 i, count: 77223 j, count: 77036 k, count: 77313 l, count: 76620 m, count: 76428 n, count: 76663 o, count: 76871 p, count: 77101 q, count: 76810 r, count: 76714 s, count: 76527 t, count: 76599 u, count: 76957 v, count: 76921 w, count: 76766 x, count: 77037 y, count: 76888 z, count: 76577 main finished 2000000 remaining 1, phase 1 |
Timer类
一个计时器,定时触发。
var myTimer = new System.Timers.Timer(1000);
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(
(o, oo) => Console.WriteLine("trigger"));
myTimer.Start();
Thread.Sleep(10000);
myTimer.Stop();
执行结果:
trigger trigger trigger trigger trigger trigger trigger trigger trigger |