zhouqijie

Parallel类

Parallel类是对线程的一个很好的抽象。该类位于System.Threading.Tasks名称空间中,提供了数据和任务并行性。

使用Parallel.For()方法循环

Parallel.For()类似for循环语句妈也是多次执行一个任务。使用Parallel.For可以并行运行迭代,迭代的顺序没有定义。

public static void Log(string prefix)
{
    WriteLine($"{prefix}, task:{Task.Current}, thread: {Thread.CurrentThread.ManagedThreadId}");
}
public static void Test()
{
    ParallelLoopResult result = Parallel.For((0, 10, i => {
        Log($"S {i}");
        Task.Delay(10).Wait();
        Log($"E {i}");
    }));
    WriteLine($"Is Complete :{result.IsCompleleted}");
}
//输出结果:  
//顺序不能保证,每次运行可以看到不同的结果  
//所有i的"S"和"E"在同一个线程打印。  
//在所有的"S"和"E"的最后才输出IsCompleted:true  


public static void Test2()
{
    ParallelLoopResult result = Parallel.For((0, 10, async i => {
        Log($"S {i}");
        await Task.Delay(10).Wait();
        Log($"E {i}");
    }));
    WriteLine($"Is Complete :{result.IsCompleleted}");
}
//输出结果:  
//i的"S"和"E"在不同的线程打印。  
//IsCompleted:True在所有的"S"之后打印,在所有的"E"之前打印。  
//(原因是Parallel只等待它创建的任务,不等待其他后台活动)  

提前停止Parallel.For

可以提前中断Parallel.For方法,而不是等待完成所有迭代。

public static void Test()
{
    ParallelLoopResult result = Parallel.For((0, 10, (int i, ParallelLoopState pls) => {
        if(i > 12)
        {
            pls.Break();
            Log($"break at {i}");
        }
    }));
    WriteLine($"Is Complete :{result.IsCompleleted}");
    WriteLine($"LowestBreakInstruction :{result.LowestBreakInstruction}");
}

Parallel.For的初始化

Parallel.For需要使用几个线程来执行循环。如果需要对线程进行初始化,就可以使用Parallel.For<TLocal>()方法。

//函数签名  
public static ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, Func<TLocal> localInit, Func<int, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);

使用Parallel.ForEach()方法循环

Parallel.ForEach()方法遍历实现了IEnumerable的集合,其方式类似foreach语句,但是以异步方式遍历。

通过Parallel.Invoke()方法调用多个方法

如果多个任务将并行运行,就可以使用Parallel.Invoke()方法,它提供了任务并行模式。

public static void Test()
{
    Parallel.Invoke(Foo1, Foo2);
}
public static void Foo1()
{
    Console.WriteLine("Foo1");
}
public static void Foo2()
{
    Console.WriteLine("Foo2");    
}

(END)