parallel類是對執行緒的抽象,提供資料與任務的並行性。類定義了靜態方法for和foreach,使用多個任務來完成多個作業。parallel.for和parallel.foreach方法在每次迭代的時候呼叫相同的**,而parallel.invoke()方法允許同時呼叫不同的方法。parallel.foreach()方法用於資料的並行性,parallel.invoke()方法用於任務的並行性。
1、for()方法
for()方法用於多次執行乙個任務,可以並行執行迭代,但迭代的順序並沒指定。for()方法前兩個引數為定義迴圈的開始和結束,第三個引數為action委託。方法的返回值是parallelloopresult結構,它提供了是否結束的資訊。如以下迴圈方法,不能保證輸出順序:
static void paralle
, task: , thread: ", i,
task.currentid, thread.currentthread.managedthreadid);
await task.delay(10);//非同步方法,用於釋放執行緒供其他任務使用。完成後,可能看不到方法的輸出,因為主(前台線)程結束,所有的後台執行緒也將結束
console.writeline(", task: , thread: ", i, task.currentid, thread.currentthread.managedthreadid);
});console.writeline("is completed: ", result.iscompleted);
}非同步功能雖然方便,但是知道後台發生了什麼仍然重要,必須留意。
提前停止for()方法
可以根據條件提前停止for()方法,而不必完成全部的迭代。,傳入引數parallelloopstate的物件,呼叫break()方法或者stop()方法。如呼叫break()方法,當迭代值大於15的時候中斷(當前執行緒結束,類似於普通for的continue),但其他任務可以同時執行,有其他值的任務也可以執行(如果當前執行緒是主線程,那麼就等同於stop(),結束所有執行緒)。stop()方法結束的是所有操作(類似於普通for的break)。利用lowestbreakiteration屬性可以忽略其他任務的結果:
static void parallelfor()
task ", i, task.currentid);
thread.sleep(10);
if (i > 15)
pls.break();
});console.writeline("is completed: ", result.iscompleted);
if (!result.iscompleted)
console.writeline("lowest break iteration: ", result.lowestbreakiteration);
}for()方法可以使用幾個執行緒執行迴圈。如果要對每個執行緒進行初始化,就需要使用到for(int, int, func, func , action)方法。
static void parallelfor()
, task ", thread.currentthread.managedthreadid, task.currentid);
return string.format("t", thread.currentthread.managedthreadid);
},(i, pls, str1) =>
str1 thread task ", i, str1, thread.currentthread.managedthreadid, task.currentid);
thread.sleep(10);
return string.format("i ", i);
},(str1) =>
", str1);
});}
2、使用foreach()方法迴圈
foreach()方法遍歷實現了ienumerable的集合,其方式類似於foreach語句,但是以非同步方式遍歷,沒有確定的順序。如果要中斷迴圈,同樣可以採用parallelloopstate引數。foreach有許多泛型的過載方法。
static void parallelforeach()
; parallelloopresult result = parallel.foreach(data, s =>
);parallel.foreach(data, (s, pls, l) =>
", s, l);
});}
3、呼叫多個方法
如果有多個任務並行,可以使用parallel.invoke()方法,它提供任務的並行性模式:
static void parallelinvoke()
static void foo()
static void bar()
4、for()方法的取消
在for()方法的過載方法中,可以傳遞乙個paralleloptions型別的引數,利用此引數可以傳遞乙個cancellationtoken引數。使用cancellationtokensource物件用於註冊cancellationtoken,並允許呼叫cancel方法用於取消操作。
一旦取消操作,for()方法就丟擲乙個operationcanceledexception型別的異常,使用cancellationtoken可以註冊取消操作時的資訊。呼叫register方法,傳遞乙個在取消操作時呼叫的委託。通過取消操作,可以將其他的迭代操作在啟動之前取消,但已經啟動的迭代操作允許完成。取消操作是以協作方式進行的,以避免在取消迭代操作的中間洩露資源。
static void cancelparallelloop()
, x =>
started", x);
int sum = 0;
for (int i = 0; i < 100; i++)
console.writeline("loop finished", 程式設計客棧x);
});} catch (operationcanceledexception ex)
}5、發現存在的問題
使用並行迴圈時,若出現以下兩個問題,需要使用partitioner(命名空間 system.collections.concurrent中)解決。
示例1中,求1000000000以內所有自然數開方的和。第一部分採用直接計算的方式,第二部分採用分割槽計算。第二部分的partitioner 會把需要迭代的區間分拆為多個不同的空間tityxgjh,並存入tuple物件中。
/* 示例1 */public static void partitionertest()
); stopwatch.stop();
console.writeline($"parallel.for:");//我的機器執行出的時間是:00:01:37.0391204
var partitioner = system.collections.concurrent.partitioner.create(0, maxvalue);//拆分區間
sum = 0;
stopwatch.restart();
parallel.foreach(partitioner, (rang) =>
private int dooperation(mathop op,int x,int y)
/** 委託會設計兩類開銷:構造開銷和呼叫開銷。大多數呼叫開銷和普通方法的呼叫差不多。 但委託是一種物件,構造開銷可能相當大,最好是只做一次構造,然後把物件快取起來。
*/ public void test()
stopwatch.stop();
console.writeline("construction and invocation: ", stopwatch.elapsed);
stopwatch.restart();
mathop op = add;//只產生一次構造開銷
for(int i=0;i<10;i++)
stopwatch.stop();
console.writeline("once construction and invocation: ", stopwatch.elapsed);
}
類和類的使用
class people name xiaoming 類屬性,類裡面的變數稱為屬性 age 18 私有屬性,別人知道後不會去動它,概念性問題 age 18 也是私有屬性,訪問會報錯 a people 例項化 print a.age 通過例項訪問類屬性,雖然是私有的,但是訪問還是可以列印,b peop...
類模板的使用 類模板使用總結
歸納以上的介紹,可以這樣宣告和使用類模板 先寫出乙個實際的類。將此類中準備改變的型別名 如int要改變為float或char 改用乙個自己指定的虛擬型別名 如上例中的t 在類宣告前面加入一行,格式為 templatetemplate class a 類體用類模板定義物件時用以下形式 類模板名 實際型...
類的使用,物件的使用
一 類的使用 class student school luffycity def eat self print yes defdrink self print drink 檢視print student.dict 增student.teacher gaohui print student.dict...