欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#用Parallel.Invoke方法盡可能并行執(zhí)行提供的每個線程

 更新時間:2024年01月22日 09:16:00   作者:wenchm  
本文主要介紹了C#用Parallel.Invoke方法盡可能并行執(zhí)行提供的每個線程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

盡可能并行執(zhí)行提供的每個操作。使用Parallel.Invoke 方法。

最簡單,最簡潔的將串行的代碼并行化。 

一、重載

Invoke(Action[])盡可能并行執(zhí)行提供的每個操作。
Invoke(ParallelOptions, Action[])執(zhí)行所提供的每個操作,而且盡可能并行運(yùn)行,除非用戶取消了操作。

二、Invoke(Action[])

盡可能并行執(zhí)行提供的每個操作。 

1.定義

public static void Invoke (params Action[] actions);

參數(shù)
actions    Action[]
要執(zhí)行的 Action 數(shù)組。

例外
ArgumentNullException
actions 參數(shù)為 null。

AggregateException
當(dāng) actions 數(shù)組中的任何操作引發(fā)異常時引發(fā)的異常。

ArgumentException
actions數(shù)組包含 null 個元素。

2.示例

 Invoke方法經(jīng)常與其他方法、匿名委托和 lambda 表達(dá)式配合使用,實現(xiàn)并行方法的線程同步。

// Parallel.Invoke()方法
// 將 Invoke 方法與其他方法、匿名委托和 lambda 表達(dá)式結(jié)合使用。
namespace ConsoleApp15
{
    class ParallelInvokeDemo
    {
        /// <summary>
        /// 執(zhí)行每個任務(wù)的線程可能不同。
        /// 不同的執(zhí)行中線程分配可能不同。
        /// 任務(wù)可能按任何順序執(zhí)行。
        /// </summary>
        static void Main()
        {
            try
            {
                Parallel.Invoke(
                    BasicAction,    // Param #0 - static method
                    () =>           // Param #1 - lambda expression
                    {
                        Console.WriteLine("Method=beta, Thread={0}", Environment.CurrentManagedThreadId);
                    },
                    delegate ()     // Param #2 - in-line delegate
                    {
                        Console.WriteLine("Method=gamma, Thread={0}", Environment.CurrentManagedThreadId);
                    }
                );
            }
            // 一般不會出現(xiàn)異常,但如萬一拋出異常, 
            // 它將被包裝在 AggregateException 中并傳播到主線程。
            catch (AggregateException e)
            {
                Console.WriteLine("An action has thrown an exception. THIS WAS UNEXPECTED.\n{0}", e.InnerException!.ToString());
            }
        }

        static void BasicAction()
        {
            Console.WriteLine("Method=alpha, Thread={0}", Environment.CurrentManagedThreadId);
        }
    }
}
// 運(yùn)行結(jié)果:
/*
Method=beta, Thread=4
Method=alpha, Thread=1
Method=gamma, Thread=10

 */

三、Invoke(ParallelOptions, Action[])

執(zhí)行所提供的每個操作,而且盡可能并行運(yùn)行,除非用戶取消了操作。

1.定義 

public static void Invoke (System.Threading.Tasks.ParallelOptions parallelOptions, params Action[] actions);

參數(shù)
parallelOptions    ParallelOptions
一個對象,用于配置此操作的行為。

actions    Action[]
要執(zhí)行的操作數(shù)組。

例外
OperationCanceledException
CancellationToken 處于 parallelOptions 設(shè)置。

ArgumentNullException
actions 參數(shù)為 null。
或 - parallelOptions 參數(shù)為 null。
AggregateException
當(dāng) actions 數(shù)組中的任何操作引發(fā)異常時引發(fā)的異常。

ArgumentException
actions數(shù)組包含 null 個元素。

ObjectDisposedException
在 parallelOptions 中與 CancellationTokenSource 關(guān)聯(lián)的 CancellationToken 已被釋放。

注解
此方法可用于執(zhí)行一組可能并行的操作。 使用結(jié)構(gòu)傳入 ParallelOptions 的取消令牌使調(diào)用方能夠取消整個操作。

2. 常用的使用方法

Parallel.Invoke(
   () => { },
   () => { },
   () => { }
   );

(1)示例1

  • 一個任務(wù)是可以分解成多個任務(wù),采用分而治之的思想;
  • 盡可能的避免子任務(wù)之間的依賴性,因為子任務(wù)是并行執(zhí)行,所以就沒有誰一定在前,誰一定在后的規(guī)定了;
  • 主線程必須等Invoke中的所有方法執(zhí)行完成后返回才繼續(xù)向下執(zhí)行。暗示以后設(shè)計并行的時候,要考慮每個Task任務(wù)盡可能差不多,如果相差很大,比如一個時間非常長,其他都比較短,這樣一個線程可能會影響整個任務(wù)的性能。這點非常重要;
  • 沒有固定的順序,每個Task可能是不同的線程去執(zhí)行,也可能是相同的;
namespace ConsoleApp16
{
    internal class Program
    {
       
        private static void Main(string[] args)
        {
            ArgumentNullException.ThrowIfNull(args);
            ParallelMothed();
            static void ParallelMothed()
            {
                Parallel.Invoke(Run1, Run2);  //這里的Run1 Run2 都是方法。
            }
        }
        static void Run1()
        {
            Console.WriteLine("我是任務(wù)一,我跑了3s");
            Thread.Sleep(3000);
        }

        static void Run2()
        {
            Console.WriteLine("我是任務(wù)二,我跑了5s");
            Thread.Sleep(5000);
        }
    }
}
//運(yùn)行結(jié)果:
/*
我是任務(wù)二,我跑了5s
我是任務(wù)一,我跑了3s

 */

(2)示例2

如果調(diào)用的方法是有參數(shù)的,如何處理?同理,直接帶上參數(shù)就可以,

Parallel.Invoke(() => Task1("task1"), () => Task2("task2"), () => Task3("task3"));
// Invoke帶參數(shù) 調(diào)用 
using System.Diagnostics;

namespace ConsoleApp17
{
    class ParallelInvoke
    {
        public static void Main(string[] args)
        {
            ArgumentNullException.ThrowIfNull(args);
            Stopwatch stopWatch = new();
            Console.WriteLine("主線程:{0}線程ID : {1};開始", "Main", Environment.CurrentManagedThreadId);
            stopWatch.Start();
            Parallel.Invoke(
                () => Task1("task1"), 
                () => Task2("task2"), 
                () => Task3("task3")
                );
            stopWatch.Stop();
            Console.WriteLine("主線程:{0}線程ID : {1};結(jié)束,共用時{2}ms", "Main", Environment.CurrentManagedThreadId, stopWatch.ElapsedMilliseconds);
            Console.ReadKey();
        }

        private static void Task1(string data)
        {
            Thread.Sleep(5000);
            Console.WriteLine("任務(wù)名:{0}線程ID : {1}", data, Environment.CurrentManagedThreadId);
        }

        private static void Task2(string data)
        {
            Console.WriteLine("任務(wù)名:{0}線程ID : {1}", data, Environment.CurrentManagedThreadId);
        }

        private static void Task3(string data)
        {
            Console.WriteLine("任務(wù)名:{0}線程ID : {1}", data, Environment.CurrentManagedThreadId);
        }
    }
}
//運(yùn)行結(jié)果:
/*
主線程:Main線程ID : 1;開始
任務(wù)名:task2線程ID : 4
任務(wù)名:task3線程ID : 7
任務(wù)名:task1線程ID : 1
主線程:Main線程ID : 1;結(jié)束,共用時5020ms
 */

(3)Stopwatch類

 提供一組方法和屬性,可用于準(zhǔn)確地測量運(yùn)行時間。

其中,Stopwatch.Start 方法和Stopwatch.Stop 方法

public class Stopwatch

使用 Stopwatch 類來確定應(yīng)用程序的執(zhí)行時間。

// 使用 Stopwatch 類來確定應(yīng)用程序的執(zhí)行時間
using System.Diagnostics;
class Program
{
    static void Main(string[] args)
    {
        ArgumentNullException.ThrowIfNull(args);

        Stopwatch stopWatch = new();
        stopWatch.Start();
        Thread.Sleep(10000);
        stopWatch.Stop();
        // Get the elapsed time as a TimeSpan value.
        TimeSpan ts = stopWatch.Elapsed;

        // Format and display the TimeSpan value.
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours, ts.Minutes, ts.Seconds,
            ts.Milliseconds / 10);
        Console.WriteLine("RunTime " + elapsedTime);
    }
}
//運(yùn)行結(jié)果:
/*
RunTime 00:00:10.01

 */
// 使用 Stopwatch 類來計算性能數(shù)據(jù)。
using System.Diagnostics;

namespace StopWatchSample
{
    class OperationsTimer
    {
        public static void Main(string[] args)
        {
            ArgumentNullException.ThrowIfNull(args);

            DisplayTimerProperties();

            Console.WriteLine();
            Console.WriteLine("Press the Enter key to begin:");
            Console.ReadLine();
            Console.WriteLine();

            TimeOperations();
        }

        public static void DisplayTimerProperties()
        {
            // Display the timer frequency and resolution.
            if (Stopwatch.IsHighResolution)
            {
                Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
            }
            else
            {
                Console.WriteLine("Operations timed using the DateTime class.");
            }

            long frequency = Stopwatch.Frequency;
            Console.WriteLine("  Timer frequency in ticks per second = {0}",frequency);
            long nanosecPerTick = (1000L * 1000L * 1000L) / frequency;
            Console.WriteLine("  Timer is accurate within {0} nanoseconds",nanosecPerTick);
        }

        private static void TimeOperations()
        {
            long nanosecPerTick = (1000L * 1000L * 1000L) / Stopwatch.Frequency;
            const long numIterations = 10000;

            // Define the operation title names.
            string[] operationNames = {"Operation: Int32.Parse(\"0\")",
                                           "Operation: Int32.TryParse(\"0\")",
                                           "Operation: Int32.Parse(\"a\")",
                                           "Operation: Int32.TryParse(\"a\")"};

            // Time four different implementations for parsing
            // an integer from a string.

            for (int operation = 0; operation &lt;= 3; operation++)
            {
                // Define variables for operation statistics.
                long numTicks = 0;
                long numRollovers = 0;
                long maxTicks = 0;
                long minTicks = long.MaxValue;
                int indexFastest = -1;
                int indexSlowest = -1;
                Stopwatch time10kOperations = Stopwatch.StartNew();

                // Run the current operation 10001 times.
                // The first execution time will be tossed
                // out, since it can skew the average time.

                for (int i = 0; i &lt;= numIterations; i++)
                {
                    long ticksThisTime = 0;
                    int inputNum;
                    Stopwatch timePerParse;

                    switch (operation)
                    {
                        case 0:
                            // Parse a valid integer using
                            // a try-catch statement.
                            // Start a new stopwatch timer.
                            timePerParse = Stopwatch.StartNew();

                            try
                            {
                                inputNum = int.Parse("0");
                            }
                            catch (FormatException)
                            {
                                inputNum = 0;
                            }

                            // Stop the timer, and save the
                            // elapsed ticks for the operation.

                            timePerParse.Stop();
                            ticksThisTime = timePerParse.ElapsedTicks;
                            break;
                        case 1:
                            // Parse a valid integer using
                            // the TryParse statement.

                            // Start a new stopwatch timer.
                            timePerParse = Stopwatch.StartNew();

                            if (!int.TryParse("0", out inputNum))
                            {
                                inputNum = 0;
                            }

                            // Stop the timer, and save the
                            // elapsed ticks for the operation.
                            timePerParse.Stop();
                            ticksThisTime = timePerParse.ElapsedTicks;
                            break;
                        case 2:
                            // Parse an invalid value using
                            // a try-catch statement.

                            // Start a new stopwatch timer.
                            timePerParse = Stopwatch.StartNew();

                            try
                            {
                                inputNum = int.Parse("a");
                            }
                            catch (FormatException)
                            {
                                inputNum = 0;
                            }

                            // Stop the timer, and save the
                            // elapsed ticks for the operation.
                            timePerParse.Stop();
                            ticksThisTime = timePerParse.ElapsedTicks;
                            break;
                        case 3:
                            // Parse an invalid value using
                            // the TryParse statement.

                            // Start a new stopwatch timer.
                            timePerParse = Stopwatch.StartNew();

                            if (!int.TryParse("a", out inputNum))
                            {
                                inputNum = 0;
                            }

                            // Stop the timer, and save the
                            // elapsed ticks for the operation.
                            timePerParse.Stop();
                            ticksThisTime = timePerParse.ElapsedTicks;
                            break;

                        default:
                            break;
                    }

                    // Skip over the time for the first operation,
                    // just in case it caused a one-time
                    // performance hit.
                    if (i == 0)
                    {
                        time10kOperations.Reset();
                        time10kOperations.Start();
                    }
                    else
                    {

                        // Update operation statistics
                        // for iterations 1-10000.
                        if (maxTicks &lt; ticksThisTime)
                        {
                            indexSlowest = i;
                            maxTicks = ticksThisTime;
                        }
                        if (minTicks &gt; ticksThisTime)
                        {
                            indexFastest = i;
                            minTicks = ticksThisTime;
                        }
                        numTicks += ticksThisTime;
                        if (numTicks &lt; ticksThisTime)
                        {
                            // Keep track of rollovers.
                            numRollovers++;
                        }
                    }
                }

                // Display the statistics for 10000 iterations.

                time10kOperations.Stop();
                long milliSec = time10kOperations.ElapsedMilliseconds;
                Console.WriteLine();
                Console.WriteLine("{0} Summary:", operationNames[operation]);
                Console.WriteLine("  Slowest time:  #{0}/{1} = {2} ticks",
                    indexSlowest, numIterations, maxTicks);
                Console.WriteLine("  Fastest time:  #{0}/{1} = {2} ticks",
                    indexFastest, numIterations, minTicks);
                Console.WriteLine("  Average time:  {0} ticks = {1} nanoseconds",
                    numTicks / numIterations,
                    (numTicks * nanosecPerTick) / numIterations);
                Console.WriteLine("  Total time looping through {0} operations: {1} milliseconds",
                    numIterations, milliSec);
            }
        }
    }
}
//運(yùn)行結(jié)果:
/*
Operations timed using the system's high-resolution performance counter.
  Timer frequency in ticks per second = 10000000
  Timer is accurate within 100 nanoseconds

 */

1.Stopwatch.Start 方法

開始或繼續(xù)測量某個時間間隔的運(yùn)行時間。

前例中有示例。 

public void Start ();

2.Stopwatch.Stop 方法

停止測量某個時間間隔的運(yùn)行時間。

public void Stop ();

前例中有示例。

到此這篇關(guān)于C#用Parallel.Invoke方法盡可能并行執(zhí)行提供的每個線程的文章就介紹到這了,更多相關(guān)C# Parallel.Invoke并行執(zhí)行提供線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • WPF中TreeView控件的用法

    WPF中TreeView控件的用法

    這篇文章介紹了WPF中TreeView控件的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • C#?將數(shù)據(jù)庫SqlServer數(shù)據(jù)綁定到類中的過程詳解

    C#?將數(shù)據(jù)庫SqlServer數(shù)據(jù)綁定到類中的過程詳解

    本文講述的是讀取數(shù)據(jù)庫中數(shù)據(jù)的常用做法,即將數(shù)據(jù)庫中的數(shù)據(jù)綁定到創(chuàng)建的類中,再將類綁定到DataGridView的數(shù)據(jù)源中的做法,對C#將SqlServer數(shù)據(jù)綁定到類中感興趣的朋友一起看看吧
    2022-06-06
  • C#中單問號(?)和雙問號(??)的用法整理

    C#中單問號(?)和雙問號(??)的用法整理

    本文詳細(xì)講解了C#中單問號(?)和雙問號(??)的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • C#解碼base64編碼二進(jìn)制數(shù)據(jù)的方法

    C#解碼base64編碼二進(jìn)制數(shù)據(jù)的方法

    這篇文章主要介紹了C#解碼base64編碼二進(jìn)制數(shù)據(jù)的方法,涉及C#中Convert類的靜態(tài)方法Convert.FromBase64String使用技巧,需要的朋友可以參考下
    2015-04-04
  • c#.net 常用函數(shù)和方法集

    c#.net 常用函數(shù)和方法集

    c#.net 常用函數(shù)和方法集 ,學(xué)習(xí)的朋友可以參考下。
    2009-07-07
  • C# JavaScriptSerializer序列化時的時間處理詳解

    C# JavaScriptSerializer序列化時的時間處理詳解

    這篇文章主要為大家詳細(xì)介紹了C# JavaScriptSerializer序列化時的時間處理詳解,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • WebService 的簡單封裝接口調(diào)用方法

    WebService 的簡單封裝接口調(diào)用方法

    這篇文章主要介紹了WebService 的簡單封裝接口調(diào)用方法,主要是通過簡單的sql語句來查詢數(shù)據(jù)庫,從而返回dataset,十分簡單實用,有需要的小伙伴可以參考下。
    2015-06-06
  • C#使用NPOI導(dǎo)出Excel類封裝

    C#使用NPOI導(dǎo)出Excel類封裝

    這篇文章主要為大家詳細(xì)介紹了C#使用NPOI導(dǎo)出Excel類封裝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#調(diào)用WebService的方法介紹

    C#調(diào)用WebService的方法介紹

    這篇文章介紹了C#調(diào)用WebService的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • 重溫C# clr 筆記總結(jié)

    重溫C# clr 筆記總結(jié)

    本篇文章是對以前學(xué)習(xí)C# clr做的一些筆記,現(xiàn)在拿出來和大家分享下,希望需要的朋友能參考一下
    2013-05-05

最新評論