.NET ヘルプ

C# 同時リスト(開発者向けの動作方法)

公開済み 2023年6月6日
共有:

共有リソースへのアクセスをめぐって複数のスレッドがせめぎ合った経験があれば、スレッドセーフの実装がゲームではないことをご存じでしょう。 心配しないでください。! C#は、スレッドセーフで汎用的なコレクションクラスの強力なスイートである並行コレクションであなたをカバーし、スタイルと優雅さでスレッドセーフを保証します。

C#35のスレッドセーフと並行コレクション

信号機のない忙しい都市の交差点を思い浮かべてみましょう。 混乱を想像してください! これは、複数のスレッドが同時に適切なシステムなしで共有リソースにアクセスする場合に発生することと同様です。 幸いなことに、C#ではスレッドのための信号機のようなものがあります - これらはコンカレントコレクションと呼ばれます。 これらは、一度に1つのスレッドだけがリソースにアクセスできるようにするコレクション・クラスです。このスレッドセーフは、複数のスレッドで作業する場合に非常に重要です。

C#35の並行スレッドセーフコレクションを探る;

C#では、名前空間 System.Collections.Concurrent には、ConcurrentDictionaryConcurrentQueueConcurrentStack、および ConcurrentBag のような様々な並行コレクションクラスがあります。 これらの順序なしコレクション・クラスは、スレッドセーフのバージョンを提供します。 並行コレクションの特徴は、順序付けされていない並行コレクションであることです。つまり、要素には特定の順序がありません。 たとえば、コンカレントリストを使用すると、アイテムがどこに挿入されるのか正確には分かりません。 重点は安全なスレッドの確保であり、順序の保持ではありません。

実際の例を見てみましょう。 ウェブサイトでのパスワード送信投稿を思い浮かべてください。並列コレクションを使用することで、複数のユーザーが同時にパスワードを送信することができます。 各'submit'アクションはスレッドのようなもので、コンカレントコレクションは、各投稿がスレッドセーフで、安全かつ効果的に処理されることを保証します。

ConcurrentDictionary:実際の例

それでは、実際の例を用いて ConcurrentDictionary コレクションクラスを探ってみましょう。 レコメンデーション機能を備えたオンライン書店を想像してください。 各ユーザーのクリックは、辞書で表される個人の推薦リストに本を追加します。 複数のユーザーが同時に本を閲覧してクリックするため、辞書に同時にアクセスする複数のスレッドがあります。

C# の ConcurrentDictionary は以下のようになる:

ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>();
ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>();
Dim recommendedBooks As New ConcurrentDictionary(Of String, String)()
VB   C#

追加を行うために、ユーザーの全ての推薦コレクションに本を追加するには、Insertメソッドを使用することができます。

public void Insert(string user, string book)
{
    recommendedBooks.TryAdd(user, book);
}
public void Insert(string user, string book)
{
    recommendedBooks.TryAdd(user, book);
}
Public Sub Insert(ByVal user As String, ByVal book As String)
	recommendedBooks.TryAdd(user, book)
End Sub
VB   C#

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

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

C#の並行コレクションは TryAdd 以外にも、TryRemoveTryUpdate など、さまざまなスレッドセーフな操作を提供する。 これらのメソッドは、一度に1つのスレッドだけが処理を実行できるようにします。したがって、例えば、前の例でユーザーのおすすめから本を削除したい場合、TryRemoveメソッドを使うことができる:

public void RemoveAt(string user)
{
    string removedBook;
    recommendedBooks.TryRemove(user, out removedBook);
}
public void RemoveAt(string user)
{
    string removedBook;
    recommendedBooks.TryRemove(user, out removedBook);
}
Public Sub RemoveAt(ByVal user As String)
	Dim removedBook As String = Nothing
	recommendedBooks.TryRemove(user, removedBook)
End Sub
VB   C#

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

同時コレクションのコピー

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

public void CopyTo()
{
    string[] bookArray = new string[recommendedBooks.Count];
    recommendedBooks.Values.CopyTo(bookArray, 0);
}
public void CopyTo()
{
    string[] bookArray = new string[recommendedBooks.Count];
    recommendedBooks.Values.CopyTo(bookArray, 0);
}
Public Sub CopyTo()
	Dim bookArray(recommendedBooks.Count - 1) As String
	recommendedBooks.Values.CopyTo(bookArray, 0)
End Sub
VB   C#

こちらで、CopyTo メソッドはすべての本をコピーします(値)recommendedBooks 並行辞書から bookArray への書き込み。

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

C#も提供していますスレッドセーフコレクションマルチスレッド環境での共有リソースへの安全なアクセスを確保するために設計されています。 これらのコレクション、例えばConcurrentBagConcurrentQueue、およびConcurrentStackは、複数のスレッドが並行してコレクションにアクセスし、変更を加えても競合やデータの破損が発生しないスレッドセーフな実装を提供します。

内部で同期を処理することにより、一貫性と整合性を保証するため、順序が必要ないコレクションが十分なシナリオや、スレッドセーフティが最も重要なC#アプリケーションに理想的です。

IronPDFについてもっと知る人気のあるC#ライブラリで、を可能にしますHTMLから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");
    }
}
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
VB   C#

一見すると並行リストとは直接関係ないように思えるかもしれませんが、IronPDFは、並行処理の結果をキャプチャするPDFレポート、ログ、またはその他のドキュメントを簡単に作成する方法を提供することにより、並行コレクション操作を補完することができます。

マルチスレッドアプリケーションで集中的なデータ処理を行うシナリオを考えてみましょう。 スレッドがデータに魔法をかける時、その結果をキャプチャしてさらなる分析や記録保存のために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) =>
{
    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) =>
{
    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)
	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
'}
VB   C#

以下はコードの出力です:

C# 同時実行リスト(開発者向けの動作説明) 図1 - 出力

結論

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

IronPDFのような外部ライブラリを統合することで、視覚的に魅力的なPDFレポートやドキュメントを生成することにより、同時コレクションの機能をさらに強化できます。 IronPDFはHTMLからPDFへの変換ライブラリの無料トライアルその機能を探索することができ、ライセンスオプションは $Lite License から始まります。

< 以前
Visual Studioとは (開発者にとっての使い方)
次へ >
Vim for Windows(開発者向けの動作方法)