Giter Club home page Giter Club logo

blog's Introduction

blog

Blog for something

blog's People

Contributors

peterluo avatar

Watchers

James Cloos avatar  avatar

blog's Issues

任务并行库

任务并行库

1、数据并行

在嵌套循环中,最有可能发生过度并行化的情况。 在多数情况下,除非满足以下一个或多个条件,否则最好仅对外部循环进行并行化:
已经知道内部循环非常长。
您正在每张订单上执行开销极大的计算。 (示例中所示的操作开销不大。)
已经知道目标系统具有足够的处理器来处理通过对 cust.Orders 查询进行并行化所产生的线程数。

Parallel.For循环

Parallel.For(0, source.Length, (i, loopState) =>
{
    // Take the first 100 values that are retrieved
    // from anywhere in the source.
    if (i < 100)
    {
        // Accessing shared object on each iteration
        // is not efficient. See remarks.
        double d = Compute(source[i]);
        results.Push(d);
    }
    else
    {
        loopState.Stop();
        return;
    }

} // Close lambda expression.
); // Close Parallel.For

Parallel.Foreach循环

Parallel.ForEach(Collection, item =>
{
    //Todo 
}

停止或者中断Parallel.For循环

Parallel.For(0, source.Length, (i, loopState) =>
{
    // Take the first 100 values that are retrieved
    // from anywhere in the source.
    if (i < 100)
    {
        // Accessing shared object on each iteration
        // is not efficient. See remarks.
        double d = Compute(source[i]);
        results.Push(d);
    }
    else
    {
        loopState.Stop();
        return;
    }

} // Close lambda expression.
); // Close Parallel.For  

Parallel.For(0, source.Length, (i, loopState) =>
{
    double d = Compute(source[i]);
    results.Push(d);
    if (d > .2)
    {
        // Might be called more than once!
        loopState.Break();
        Console.WriteLine("Break called at iteration {0}. d = {1} ", i, d);
        Thread.Sleep(1000);
    }
});

具有本地变量的Parallel.For循环

class Test
{
    static void Main()
    {
        int[] nums = Enumerable.Range(0, 1000000).ToArray();
        long total = 0;

        // Use type parameter to make subtotal a long, not an int
        Parallel.For<long>(0, nums.Length, () => 0, (j, loop, subtotal) =>
        {
            subtotal += nums[j];
            return subtotal;
        },
            (x) => Interlocked.Add(ref total, x)
        );

        Console.WriteLine("The total is {0}", total);
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}
  • 每个 For 方法的前两个参数都指定起始迭代值和结束迭代值;
  • 第三个参数的类型为 Func,其中 TResult 是将存储线程本地状态的变量的类型;
  • 第四个类型参数是在其中定义循环逻辑的参数;

IntelliSense 显示其类型为 Func<int, ParallelLoopState, long, long> 或 Func(Of Integer, ParallelLoopState, Long, Long)。
lambda 表达式按对应于这些类型的相同顺序需要三个输入参数。 最后一个类型参数是返回类型。 在这种情况下,类型为 long,因为该类型是我们在For类型参数中指定的类型。 我们在 lambda 表达式中调用该变量subtotal,并将其返回。返回值用于在每个后续的迭代上初始化小计。
您也可以将此最后一个参数简单地看作传递到每个迭代,然后在最后一个迭代完成时传递到 localFinally 委托的值。

  • 第五个参数是在其中定义方法的参数,当此线程上的所有迭代均已完成后,将调用该方法一次。

具有本地变量的Parallel.Foreach循环

static void Main()
{
    int[] nums = Enumerable.Range(0, 1000000).ToArray();
    long total = 0;

    // First type parameter is the type of the source elements
    // Second type parameter is the type of the local data (subtotal)
    Parallel.ForEach<int, long>(nums, // source collection
                                () => 0, // method to initialize the local variable
                                (j, loop, subtotal) => // method invoked by the loop on each iteration
                                {
                                    subtotal += nums[j]; //modify local variable
                                    return subtotal; // value to be passed to next iteration
                                },
        // Method to be executed when all loops have completed.
        // finalResult is the final value of subtotal. supplied by the ForEach method.
                                (finalResult) => Interlocked.Add(ref total, finalResult)
                                );

    Console.WriteLine("The total from Parallel.ForEach is {0}", total);
    Console.WriteLine("Press any key to exit");
    Console.ReadKey();
}

若要在 ForEach 循环中使用线程本地变量,您必须使用采用两个 type 参数的方法版本。 第一个参数指定源元素的类型,第二个参数指定线程本地变量的类型。
第一个输入参数是数据源,第二个输入参数是对线程本地变量进行初始化的函数。 第三个输入参数是 Func<T1, T2, T3, TResult>,每个迭代上的并行循环将调用该参数。 您为委托提供代码,并且循环将传入输入参数。 输入参数为当前元素、一个使您能够检查循环状态的 ParallelLoopState 变量,以及线程本地变量。 您返回线程本地变量,方法随后会将其传递到此分区上的下一个迭代。 此变量在所有循环分区上都不同。
ForEach 方法的最后一个输入参数是 Action 委托,当所有循环完成时,方法将调用该委托。 方法为此线程(或循环分区)提供线程本地变量的最终值,并且您提供代码,该代码捕获最终值,并执行将此分区中的结果和其他分区中的结果进行合并所需的>任何操作。 由于委托类型为 Action,因此没有返回值。

取消 Parallel.For 或 ForEach Loop

namespace CancelParallelLoops
{
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;

    class Program
    {
        static void Main()
        {
            int[] nums = Enumerable.Range(0, 10000000).ToArray();
            CancellationTokenSource cts = new CancellationTokenSource();

           // Use ParallelOptions instance to store the CancellationToken
            ParallelOptions po = new ParallelOptions();
            po.CancellationToken = cts.Token;
            po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
            Console.WriteLine("Press any key to start. Press 'c' to cancel.");
            Console.ReadKey();

            // Run a task so that we can cancel from another thread.
            Task.Factory.StartNew(() =>
            {
                if (Console.ReadKey().KeyChar == 'c')
                    cts.Cancel();
                Console.WriteLine("press any key to exit");
            });

            try
            {
                Parallel.ForEach(nums, po, (num) =>
                {
                    double d = Math.Sqrt(num);
                    Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId);
                    po.CancellationToken.ThrowIfCancellationRequested();
                });
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadKey();
        }
    }
}

2、任务并行库

延续任务

// The antecedent task. Can also be created with Task.Factory.StartNew.
Task<DayOfWeek> taskA = new Task<DayOfWeek>(() => DateTime.Today.DayOfWeek);

// The continuation. Its delegate takes the antecedent task
// as an argument and can return a different type.
Task<string> continuation = taskA.ContinueWith((antecedent) =>
{
    return String.Format("Today is {0}.",
                        antecedent.Result);
});

// Start the antecedent.
taskA.Start();

// Use the contuation's result.
Console.WriteLine(continuation.Result);
Console.Read();

已附加和已分离的子任务
分离的子任务

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var parent = Task.Factory.StartNew(() => {
         Console.WriteLine("Outer task executing.");

         var child = Task.Factory.StartNew(() => {
            Console.WriteLine("Nested task starting.");
            Thread.SpinWait(500000);
            Console.WriteLine("Nested task completing.");
         });
      });

      parent.Wait();
      Console.WriteLine("Outer has completed.");
   }
}
// The example produces output like the following:
//        Outer task executing.
//        Nested task starting.
//        Outer has completed.
//        Nested task completing.

附加的子任务

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var parent = Task.Factory.StartNew(() => {
            Console.WriteLine("Parent task executing.");
            var child = Task.Factory.StartNew(() => {
                  Console.WriteLine("Attached child starting.");
                  Thread.SpinWait(5000000);
                  Console.WriteLine("Attached child completing.");
            }, TaskCreationOptions.AttachedToParent);
      });
      parent.Wait();
      Console.WriteLine("Parent has completed.");
   }
}
// The example displays the following output:
//       Parent task executing.
//       Attached child starting.
//       Attached child completing.
//       Parent has completed.

使用Parallel.Invoke来执行并行任务

namespace ParallelTasks
{
    using System;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Net;

    class ParallelInvoke
    {
        static void Main()
        {
            // Retrieve Darwin's "Origin of the Species" from Gutenberg.org.
            string[] words = CreateWordArray(@"http://www.gutenberg.org/files/2009/2009.txt");

            #region ParallelTasks
            // Perform three tasks in parallel on the source array
            Parallel.Invoke(() =>
                            {
                                Console.WriteLine("Begin first task...");
                                GetLongestWord(words);
                            },  // close first Action

                            () =>
                            {
                                Console.WriteLine("Begin second task...");
                                GetMostCommonWords(words);
                            }, //close second Action

                            () =>
                            {
                                Console.WriteLine("Begin third task...");
                                GetCountForWord(words, "species");
                            } //close third Action
                         ); //close parallel.invoke

            Console.WriteLine("Returned from Parallel.Invoke");
            #endregion

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }

        #region HelperMethods
        private static void GetCountForWord(string[] words, string term)
        {
            var findWord = from word in words
                           where word.ToUpper().Contains(term.ToUpper())
                           select word;

            Console.WriteLine(@"Task 3 -- The word ""{0}"" occurs {1} times.",
                term, findWord.Count());
        }

        private static void GetMostCommonWords(string[] words)
        {
            var frequencyOrder = from word in words
                                 where word.Length > 6
                                 group word by word into g
                                 orderby g.Count() descending
                                 select g.Key;

            var commonWords = frequencyOrder.Take(10);

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Task 2 -- The most common words are:");
            foreach (var v in commonWords)
            {
                sb.AppendLine("  " + v);
            }
            Console.WriteLine(sb.ToString());
        }

        private static string GetLongestWord(string[] words)
        {
            var longestWord = (from w in words
                               orderby w.Length descending
                               select w).First();

            Console.WriteLine("Task 1 -- The longest word is {0}", longestWord);
            return longestWord;
        }


        // An http request performed synchronously for simplicity.
        static string[] CreateWordArray(string uri)
        {
            Console.WriteLine("Retrieving from {0}", uri);

            // Download a web page the easy way.
            string s = new WebClient().DownloadString(uri);

            // Separate string into an array of words, removing some common punctuation.
            return s.Split(
                new char[] { ' ', '\u000A', ',', '.', ';', ':', '-', '_', '/' },
                StringSplitOptions.RemoveEmptyEntries);
        }
        #endregion
    }

    /* Output (May vary on each execution):
        Retrieving from http://www.gutenberg.org/dirs/etext99/otoos610.txt
        Response stream received.
        Begin first task...
        Begin second task...
        Task 2 -- The most common words are:
          species
          selection
          varieties
          natural
          animals
          between
          different
          distinct
          several
          conditions

        Begin third task...
        Task 1 -- The longest word is characteristically
        Task 3 -- The word "species" occurs 1927 times.
        Returned from Parallel.Invoke
        Press any key to exit  
     */
}

函数 @@IDENTITY, SCOPE_IDENTITY(), IDENT_CURRENT('tablename')的用法

@@IDENTITY

@@IDENTITY返回的是当前会话中最后一次插入表单数据所在的标识值。
这个地方需要对当前会话做个解释:连接一次数据库、打开一个查询分析器窗口执行SQL脚本、处理一次web对数据库的调用就是一次会话。

  • 在当前会话中,如果有两个表单插入,那就返回最后一个表单的标识值;
  • 表单有一个INSERT触发器,向另外表单B插入有标识值的数据,那么返回的是表单B的标识值;
  • 会话中有调用存储过程执行INSERT操作的,会返回存储过程中所涉及到表单最后一次插入的标识值.

eg:

create table table1 (col1 int identity(1,1), col2 varchar(100))    
create table table2 (col1 int identity(20,1), col2 varchar(100))  

INSERT table1 VALUES ('book')  
INSERT table2 VALUES ('kindle')  

select @@IDENTITY    -- 返回的是最后一张表标识值  20  

我们再打开另外一个查询分析器执行:

INSERT table2 VALUES ('kindle')
select @@IDENTITY  -- 返回的是标识值  21

然后在第一个查询分析器中执行:

select @@IDENTITY   -- 发现返回的还是当前会话中的最后一次标识值  20

注意:当表单中有触发器或者其它存储过程执行时,注意要返回的标识值是否是我们所需。

SCOPE_IDENTITY()

SCOPE_IDENTITY()官方定义:it returns the last identity value generated for any table, not just in the current session, but also for the current scope.

  • 我的理解是:返回的不仅是当前会话当中,也是当前上下文执行的最后插入的标识值。
    相对于@@IDENTITY,SCOPE_IDENTITY()返回值范围更窄一些。

eg:
创建一个表单,创建这个表单的一个INSERT存储过程:

create table table3 (col1 int identity(1,1), col2 varchar(100))
GO

CREATE PROC InsertRow1 @value varchar(100)
AS
INSERT table3 VALUES (@value)
RETURN 0
GO

执行一个INSERT语句:
-- Insert row 1
INSERT table3 VALUES ('bork')

select @@IDENTITY           [@@Identity],   -- Returns 1
SCOPE_IDENTITY()        [SCOPE_IDENTITY]    -- Returns 1
FROM table3

然后,我们用存储过程执行,插入一条数据:

-- Run procedure to insert row 2
exec InsertRow1 'borkbork'

select @@IDENTITY           [@@Identity],   -- Returns 2
SCOPE_IDENTITY()        [SCOPE_IDENTITY]    -- 仍然返回的是  1!
FROM table3

好玩吧,^_^。

IDENT_CURRENT('tablename')

IDENT_CURRENT('表名')这个是最好理解的:返回无论何时何地(没有会话限制,没有上下文限制)插入的最后一条标识值。
可以在多个查询分析器中插入数据,然后在一个查询分析器中执行下面语句查看:

SELECT IDENT_CURRENT('table3')  --每次INSERT 都会返回最后一次的标识值  

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.