フッターコンテンツにスキップ
.NETヘルプ

C# Concurrent List (開発者向けの仕組み)

もし複数のスレッドが共有リソースへのアクセスを争っていることがあったなら、スレッドセーフな実装がゲームではないことをご存じでしょう。 しかし心配しないでください! C#にはコンカレントコレクションがあります - スレッドの安全性をスタイルと優雅さで確保する強力なスイートのスレッドセーフな汎用コレクションクラスです。

C#におけるスレッドセーフティとコンカレントコレクション

交通信号がない忙しい都市の交差点を思い描きましょう。 混乱を想像できますか! これは、適切なシステムがない場合に複数のスレッドが同時に共有リソースにアクセスする際に発生する現象と似ています。 幸いなことに、C#ではスレッドの交通信号があります - それがコンカレントコレクションと呼ばれます。 これらは、一度に一つのスレッドがリソースにアクセスできるようにするコレクションクラスです。このスレッドセーフティは、複数のスレッドを扱う際に重要です。

C#でのコンカレントスレッドセーフコレクションの探求

C#のSystem.Collections.Concurrent名前空間には、ConcurrentDictionaryConcurrentQueueConcurrentStackConcurrentBagのような様々なコンカレントコレクションクラスがあります。 これらの無秩序なコレクションクラスは、非コンカレントの対応するクラスのスレッドセーフ版を提供します。 コンカレントコレクションを他と区別するのは、それが無秩序なコンカレントコレクションであるということであり、要素に特定の順序がないことを意味します。 例えば、コンカレントリストでは、要素がどこに挿入されるのか正確にはわかりません。 注目すべきは、スレッドセーフティを確保することであり、順序を維持することではありません。

実生活の例を見てみましょう。 ウェブサイト上でのパスワード提出の投稿を考えてみてください。コンカレントコレクションを使用すると、複数のユーザーが同時にパスワードを提出できます。 各「提出」アクションはスレッドのようであり、コンカレントコレクションは各提出がスレッドセーフで、安全かつ効果的に処理されることを保証します。

ConcurrentDictionary: 実例

ConcurrentDictionaryコレクションクラスを実例で探求しましょう。 オンライン書店での推奨機能をイメージしてください。 各ユーザーのクリックが、辞書で表された彼らの個人的な推奨リストに本を追加します。 複数のユーザーが同時に本を閲覧しクリックするため、辞書に同時にアクセスする複数のスレッドがあります。

C#のConcurrentDictionaryは次のようになります:

using System.Collections.Concurrent;

ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>();
using System.Collections.Concurrent;

ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>();
Imports System.Collections.Concurrent

Private recommendedBooks As New ConcurrentDictionary(Of String, String)()
$vbLabelText   $csharpLabel

ユーザーの推奨全体に本を追加するために、TryAddメソッドを使用できます:

public void Insert(string user, string book)
{
    // Try to add the book to the user's recommendations
    recommendedBooks.TryAdd(user, book);
}
public void Insert(string user, string book)
{
    // Try to add the book to the user's recommendations
    recommendedBooks.TryAdd(user, book);
}
Public Sub Insert(ByVal user As String, ByVal book As String)
	' Try to add the book to the user's recommendations
	recommendedBooks.TryAdd(user, book)
End Sub
$vbLabelText   $csharpLabel

このシナリオでは、ConcurrentDictionaryコレクションクラスは、各クリック(または「スレッド」)が個別に対処され、ユーザーの推奨が混同されないようにし、すべてのスレッドセーフティを処理するため、データ競合や複数のスレッドに関連するその他の競合の問題を心配する必要はありません。

スレッドセーフな操作の実装

TryAdd以外にも、C#のコンカレントコレクションでは、TryRemoveTryUpdateなど、様々なスレッドセーフな操作を提供します。 これらのメソッドは、一度に一つのスレッドのみが操作を実行できることを保証します。例えば、前の例でユーザーの推奨から本を削除したい場合、TryRemoveメソッドを使用できます。

public void RemoveAt(string user)
{
    // Attempt to remove the book for the specified user
    string removedBook;
    recommendedBooks.TryRemove(user, out removedBook);
}
public void RemoveAt(string user)
{
    // Attempt to remove the book for the specified user
    string removedBook;
    recommendedBooks.TryRemove(user, out removedBook);
}
Public Sub RemoveAt(ByVal user As String)
	' Attempt to remove the book for the specified user
	Dim removedBook As String = Nothing
	recommendedBooks.TryRemove(user, removedBook)
End Sub
$vbLabelText   $csharpLabel

TryRemoveメソッドは、提供されたキー(この場合はユーザー)の値を削除しremovedBook変数に入れようとします。

コンカレントコレクションのコピー

さて、コンカレントコレクションを配列にコピーしたいとしましょう。 コンカレントコレクションはまさにこの目的のためにCopyToメソッドを提供します:

public void CopyTo()
{
    // Create an array to hold the recommended books
    string[] bookArray = new string[recommendedBooks.Count];

    // Copy the values of the concurrent dictionary to the array
    recommendedBooks.Values.CopyTo(bookArray, 0);
}
public void CopyTo()
{
    // Create an array to hold the recommended books
    string[] bookArray = new string[recommendedBooks.Count];

    // Copy the values of the concurrent dictionary to the array
    recommendedBooks.Values.CopyTo(bookArray, 0);
}
Public Sub CopyTo()
	' Create an array to hold the recommended books
	Dim bookArray(recommendedBooks.Count - 1) As String

	' Copy the values of the concurrent dictionary to the array
	recommendedBooks.Values.CopyTo(bookArray, 0)
End Sub
$vbLabelText   $csharpLabel

ここで、CopyToメソッドはrecommendedBooksコンカレントディクショナリのすべての本(値)をbookArrayにコピーします。

スレッドセーフコレクション

C#はマルチスレッド環境で共有リソースへの安全なアクセスを保証するスレッドセーフコレクションも提供します。 これらのコレクション、例えばConcurrentBagConcurrentQueueConcurrentStackは、同時に複数のスレッドがコレクションにアクセスして変更する際に衝突やデータ損傷を避けるスレッドセーフな実装を提供します。

内部的に同期を処理することで一貫性と完全性を保証し、無秩序なコレクションが十分で、C#アプリケーションでスレッドセーフティが最も重要なシナリオに理想的です。

Learn More About IronPDF is a popular C# library that allows you to IronPDFの詳細を学ぶは、HTMLからPDFドキュメントを簡単に生成するための人気のあるC#ライブラリです。

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

		' 1. Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' 2. Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel

最初はコンカレントリストとは直接関係ないように見えますが、IronPDFはコンカレントコレクション操作を補完し、コンカレント処理の結果をキャプチャする報告書やログ、その他のドキュメントを作成する簡単な方法を提供します。

集中的なデータ処理を行うマルチスレッドアプリケーションがあるシナリオを考えてみてください。 スレッドがデータを魔法にかけている間に、結果をキャプチャし、さらなる分析や記録のためにPDFレポートを生成したくなるかもしれません。 ここでIronPDFが役立ちます。

IronPDFを使用するのは、ライブラリをプロジェクトに追加し、その便利なAPIを利用するだけです。 IronPDFをコンカレントコレクション操作と統合する方法の例を次に示します:

using IronPdf;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;

// Create a concurrent dictionary to hold your processed data
ConcurrentDictionary<int, string> processedData = new ConcurrentDictionary<int, string>();

// Define your data list (replace with your actual data source)
List<DataItem> dataList = GetDataList();

// Process your data concurrently and store the results in the dictionary
Parallel.ForEach(dataList, (dataItem) =>
{
    // Process each data item and add the result to the dictionary
    string processedResult = ProcessDataItem(dataItem);
    processedData.TryAdd(dataItem.Id, processedResult);
});

// Generate a PDF report with the processed data
var renderer = new ChromePdfRenderer();
var pdfDocument = renderer.RenderHtmlAsPdf(BuildHtmlReport(processedData));
pdfDocument.SaveAs("C:\\processed_data_report.pdf");

// Method to retrieve the data list (replace with your actual data source logic)
List<DataItem> GetDataList()
{
    List<DataItem> dataList = new List<DataItem>()
    {
        new DataItem { Id = 1, Name = "Item 1" },
        new DataItem { Id = 2, Name = "Item 2" },
        new DataItem { Id = 3, Name = "Item 3" },
        new DataItem { Id = 4, Name = "Item 4" }
    };
    return dataList;
}

// Method to process each data item and return the result (replace with your actual data processing logic)
string ProcessDataItem(DataItem dataItem)
{
    // Simulating data processing with a delay
    Task.Delay(100).Wait();
    return $"Processed: {dataItem.Name}";
}

// Method to build the HTML report using the processed data (replace with your actual reporting logic)
string BuildHtmlReport(ConcurrentDictionary<int, string> processedData)
{
    string html = "<h1>Processed Data Report</h1><ul>";
    foreach (var kvp in processedData)
    {
        html += $"<li>Item {kvp.Key}: {kvp.Value}</li>";
    }
    html += "</ul>";
    return html;
}

// Placeholder class for your data item (replace with your actual data item class)
public class DataItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    // Add other properties as needed
}
using IronPdf;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;

// Create a concurrent dictionary to hold your processed data
ConcurrentDictionary<int, string> processedData = new ConcurrentDictionary<int, string>();

// Define your data list (replace with your actual data source)
List<DataItem> dataList = GetDataList();

// Process your data concurrently and store the results in the dictionary
Parallel.ForEach(dataList, (dataItem) =>
{
    // Process each data item and add the result to the dictionary
    string processedResult = ProcessDataItem(dataItem);
    processedData.TryAdd(dataItem.Id, processedResult);
});

// Generate a PDF report with the processed data
var renderer = new ChromePdfRenderer();
var pdfDocument = renderer.RenderHtmlAsPdf(BuildHtmlReport(processedData));
pdfDocument.SaveAs("C:\\processed_data_report.pdf");

// Method to retrieve the data list (replace with your actual data source logic)
List<DataItem> GetDataList()
{
    List<DataItem> dataList = new List<DataItem>()
    {
        new DataItem { Id = 1, Name = "Item 1" },
        new DataItem { Id = 2, Name = "Item 2" },
        new DataItem { Id = 3, Name = "Item 3" },
        new DataItem { Id = 4, Name = "Item 4" }
    };
    return dataList;
}

// Method to process each data item and return the result (replace with your actual data processing logic)
string ProcessDataItem(DataItem dataItem)
{
    // Simulating data processing with a delay
    Task.Delay(100).Wait();
    return $"Processed: {dataItem.Name}";
}

// Method to build the HTML report using the processed data (replace with your actual reporting logic)
string BuildHtmlReport(ConcurrentDictionary<int, string> processedData)
{
    string html = "<h1>Processed Data Report</h1><ul>";
    foreach (var kvp in processedData)
    {
        html += $"<li>Item {kvp.Key}: {kvp.Value}</li>";
    }
    html += "</ul>";
    return html;
}

// Placeholder class for your data item (replace with your actual data item class)
public class DataItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    // Add other properties as needed
}
Imports IronPdf
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Threading.Tasks

' Create a concurrent dictionary to hold your processed data
Private processedData As New ConcurrentDictionary(Of Integer, String)()

' Define your data list (replace with your actual data source)
Private dataList As List(Of DataItem) = GetDataList()

' Process your data concurrently and store the results in the dictionary
Parallel.ForEach(dataList, Sub(dataItem)
	' Process each data item and add the result to the dictionary
	Dim processedResult As String = ProcessDataItem(dataItem)
	processedData.TryAdd(dataItem.Id, processedResult)
End Sub)

' Generate a PDF report with the processed data
Dim renderer = New ChromePdfRenderer()
Dim pdfDocument = renderer.RenderHtmlAsPdf(BuildHtmlReport(processedData))
pdfDocument.SaveAs("C:\processed_data_report.pdf")

' Method to retrieve the data list (replace with your actual data source logic)
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'List(Of DataItem) GetDataList()
'{
'	List<DataItem> dataList = New List<DataItem>() { New DataItem { Id = 1, Name = "Item 1" }, New DataItem { Id = 2, Name = "Item 2" }, New DataItem { Id = 3, Name = "Item 3" }, New DataItem { Id = 4, Name = "Item 4" } };
'	Return dataList;
'}

' Method to process each data item and return the result (replace with your actual data processing logic)
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'string ProcessDataItem(DataItem dataItem)
'{
'	' Simulating data processing with a delay
'	Task.Delay(100).Wait();
'	Return string.Format("Processed: {0}", dataItem.Name);
'}

' Method to build the HTML report using the processed data (replace with your actual reporting logic)
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'string BuildHtmlReport(ConcurrentDictionary(Of int, string) processedData)
'{
'	string html = "<h1>Processed Data Report</h1><ul>";
'	foreach (var kvp in processedData)
'	{
'		html += string.Format("<li>Item {0}: {1}</li>", kvp.Key, kvp.Value);
'	}
'	html += "</ul>";
'	Return html;
'}

' Placeholder class for your data item (replace with your actual data item class)
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'public class DataItem
'{
'	public int Id
'	{
'		get;
'		set;
'	}
'	public string Name
'	{
'		get;
'		set;
'	}
'	' Add other properties as needed
'}
$vbLabelText   $csharpLabel

ここにコードの出力があります:

C# Concurrent List (開発者向け) 図1 - 出力

結論

結論として、C#のコンカレントコレクション、例えばコンカレントリストを理解し、利用することは、マルチスレッドシナリオを効率的に処理し、アプリケーションでスレッドセーフティを確保する能力を大幅に向上させます。 コンカレントコレクションを使用することで、共有リソースを効果的に管理し、スレッド間のデータ競合や衝突を防ぐことができます。

外部ライブラリのIronPDFを統合することで、視覚的に魅力的なPDFレポートやドキュメントの生成を可能にし、コンカレントコレクションの機能をさらに拡張できます。 IronPDFはHTMLからPDF変換のためのライブラリの無料トライアルを提供し、その機能を試してみて、ライセンスオプションは$799から始まります。

よくある質問

C# の同時実行コレクションとは?

C# の同時実行コレクションは、複数のスレッドが共有リソースにアクセスするときのスレッド セーフ性を確保する、スレッド セーフなジェネリック コレクション クラスのスイートです。

なぜ C# でのスレッド セーフティが重要なのですか?

C# でのスレッド セーフティは、複数のスレッドが共有リソースに同時にアクセスして変更する際に、混乱やデータの破損を防ぐために重要です。操作が制御された方法で実行されることを保証します。

C# でスレッドセーフなリストを作成するにはどうすればよいですか?

C# では直接スレッドセーフな List クラスは提供されていませんが、`ConcurrentBag` や `ConcurrentDictionary` などの他の同時実行コレクションを使用して、同様のスレッドセーフな操作を行うことができます。

C# の ConcurrentDictionary とは?

C# の ConcurrentDictionary は、`System.Collections.Concurrent` 名前空間内のスレッド セーフなコレクションクラスです。複数のスレッドがキーと値のペアを同時に安全に追加、更新、および削除できるようにします。

ConcurrentDictionary はどのようにしてスレッド セーフティを確保しますか?

ConcurrentDictionary は内部的に同期を処理し、1 回に 1 つのスレッドのみがアイテムの追加や削除などの操作を実行できるようにすることで、スレッド セーフティを確保します。

ConcurrentDictionary にアイテムを追加するにはどうすればよいですか?

TryAdd メソッドを使用して ConcurrentDictionary にアイテムを追加できます。このメソッドは、キーが既に辞書に存在しない場合にのみキーと値のペアを追加しようとします。

Concurrent コレクションの CopyTo メソッドの目的は何ですか?

同時実行コレクションの CopyTo メソッドは、コレクションの要素を配列にコピーするために使用され、コレクションから別のストレージ形式にデータを転送するための方法を提供します。

IronPDF を使用して処理済みデータから PDF レポートを生成できますか?

はい、IronPDF を使用して、同時実行操作の結果をキャプチャし、マルチスレッド アプリケーションによって処理されたデータから PDF レポートを生成できます。

IronPDF を使用することで、同時実行操作の機能はどのように強化されますか?

IronPDF は、プロセスされたデータから PDF ドキュメントを作成できるようにすることで、同時実行操作を強化し、マルチスレッド処理の結果を文書化して共有する方法を提供します。

マルチスレッドの C# アプリケーションで IronPDF が果たす役割は何ですか?

IronPDF を使用すると、開発者は並列で処理されたデータから PDF レポートを生成でき、マルチスレッド操作からの結果を統合して共有しやすくなります。

Curtis Chau
テクニカルライター

Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。

開発以外にも、CurtisはIoT(Internet of Things)への強い関心を持ち、ハードウェアとソフトウェアの統合方法を模索しています。余暇には、ゲームをしたりDiscordボットを作成したりして、技術に対する愛情と創造性を組み合わせています。