我撰寫了一個執行緒測驗應用程式來查看多個并行啟動的執行緒回傳行為。我是異步編程的新手,所以你能評論一下這段代碼嗎?
我創建了多個TestThreadClass使用 Parallel 的實體來查看異步操作同時完成時發生的情況。執行緒完成后,我將它們添加到執行緒安全字典 ( ConcurrentDictionary) 中,并帶有隨機生成的 guid。
下面是一個隨機的異步類在 1 毫秒內回傳;
public class TestThreadClass
{
private Task<ThreadResultModel> myTask;
public readonly int myNumber;
public readonly string myId;
public TestThreadClass(int _myNumber)
{
myNumber = _myNumber;
myId = Guid.NewGuid().ToString();
}
public async Task<ThreadResultModel> StartOperation()
{
myTask = InvokeOperation();
return await myTask;
}
private async Task<ThreadResultModel> InvokeOperation()
{
await Task.Delay(TimeSpan.FromMilliseconds(1));
return new ThreadResultModel(myNumber, myId, "Returned");
}
}
下面是我使用 WinForms 應用程式的創建者類。我啟動并行執行緒,并在它們完成后將它們填充到 aGridView以比較回傳毫秒數;
public partial class Form1 : Form
{
private const int threadNumber = 100;
private readonly ConcurrentDictionary<string, ThreadResultModel> startedConcurrentDictionary;
private readonly ConcurrentDictionary<string, ThreadResultModel> returnedConcurrentDictionary;
public Form1()
{
InitializeComponent();
startedConcurrentDictionary = new ConcurrentDictionary<string, ThreadResultModel>();
returnedConcurrentDictionary = new ConcurrentDictionary<string, ThreadResultModel>();
}
private void Form1_Load(object sender, EventArgs e)
{
FillComboboxes();
}
private void FillComboboxes()
{
for (int i = 1; i <= threadNumber; i )
{
DdlThreadNumber.Items.Add(i.ToString());
}
}
private void BtnStartThreads_Click(object sender, EventArgs e)
{
Parallel.For(0, int.Parse(DdlThreadNumber.Text), StartAThread);
}
private void StartAThread(int threadTag)
{
TestThreadClass t = new TestThreadClass(threadTag);
startedConcurrentDictionary.TryAdd(t.myId, new ThreadResultModel(threadTag, t.myId, "Started"));
t.StartOperation().ContinueWith(result =>
{
returnedConcurrentDictionary.TryAdd(result.Result.MyId, result.Result);
});
}
private void BtnReport_Click(object sender, EventArgs e)
{
foreach (var item in startedConcurrentDictionary)
{
GrdThreads.Rows.Add(item.Value.MyNumber, item.Value.MyId, item.Value.EventType, item.Value.Time);
}
foreach (var item in returnedConcurrentDictionary)
{
GrdThreads.Rows.Add(item.Value.MyNumber, item.Value.MyId, item.Value.EventType, item.Value.Time);
}
}
private void GrdThreads_SelectionChanged(object sender, EventArgs e)
{
statusLabel.Text = GrdThreads.SelectedRows.Count.ToString();
}
}
我只想知道這種方法是否正確。
uj5u.com熱心網友回復:
我只想知道這種方法是否正確。
這個問題的答案取決于您要實作的目標。上面代碼的作用是:
Parallel.For一次執行多個專案,但不是全部。它在底層調度程式上運行 100 次呼叫,一次執行的次數取決于 CPU 內核的數量。但它不會為每次呼叫啟動新執行緒,只是重新使用現有執行緒- 每個
StartAThread都不會啟動一個執行緒。它們只是在 Parallel.For 調度程式的執行緒上運行,直到await. 之后,它們從任何執行緒中消失,經過一段時間的延遲,它們被添加到ThreadPool ThreadPool在awaits之后執行作業,負載平衡其執行緒之間的呼叫ContinueWith方法中的代碼也添加在ThreadPool
因此,僅使用awaitorParallel.For不會創建 100 個執行緒。由于創建執行緒很慢并且每個執行緒都占用大量記憶體,因此所有這些功能都將使用一些內部機制來重用現有執行緒,因為您不需要比 CPU 可以處理的更多執行緒
但是您仍然創建了 100 個并發任務,全部分成幾個部分(使用await或ContinueWith),ThreadPool在多個執行緒上獨立運行(通常大約是 CPU 內核/執行緒的數量)。
如果你真的想創建 100 個執行緒,你需要使用new Thread(...)call
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/321443.html
下一篇:獲取檔案名的目錄
