Erstellen Sie eine PDF-Datei mit effizienter Speicherverwaltung. Sehen Sie sich die Ergebnisse in Aktion an!
using IronPdf;
using System;
var data = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var span = new Span<int>(data, 2, 5); // Create a Span that includes elements from index 2 to 6
// Convert the span to a string for HTML content
string spanContent = string.Join(", ", span.ToArray());
// Create HTML content with the span data
string htmlContent = $"<h1>Span Data PDF</h1><p>The data in the span is: {spanContent}</p>";
// Initialize ChromePdfRenderer
var renderer = new ChromePdfRenderer();
// Render the HTML content as PDF
var pdfDocument = renderer.RenderHtmlAsPdf(htmlContent);
// Save the PDF file
string fileName = "SpanData.pdf";
pdfDocument.SaveAs(fileName);
Console.WriteLine($"PDF saved as: {fileName}");
Span ist ein Typ, der in C# 7.2 als Teil der Span-Struktur im System-Namespace eingeführt wurde. Er ist so konzipiert, dass er einen zusammenhängenden Bereich eines beliebigen Speichers darstellt. Im Gegensatz zu Arrays oder Sammlungen wie dem verwalteten Heap besitzt Span nicht den Stapelspeicher oder den Speicherbereich, auf den es zeigt; stattdessen bietet es eine leichtgewichtige Sicht auf vorhandene Speicherblöcke. Diese Eigenschaft macht Span besonders leistungsfähig für Szenarien, in denen Sie effizient mit Speicherpuffern arbeiten müssen, ohne zusätzlichen Overhead und unsichere Codeszenarien zu verursachen. Später in diesem Artikel werden wir auch die Einführung in die IronPDF-Bibliothek von Iron Software sehen.
Hauptmerkmale der Spanne
1. Speicherverwaltung
Span in C# ermöglicht es Entwicklern, direkt mit Speicher zu arbeiten, ohne auf traditionelle Heap-Zuweisungen zurückgreifen zu müssen. Es bietet eine Möglichkeit, Speicherabschnitte aus bestehenden Arrays oder anderen Speicherquellen zu erstellen, wodurch zusätzliche Speicherkopien überflüssig werden.
2. Null-Kopie-Abstraktionen
Eines der herausragenden Merkmale von C# Span sind seine Null-Kopie-Abstraktionen. Anstatt Daten zu duplizieren, bietet Span eine Möglichkeit, effizient auf vorhandenen Speicher zu verweisen. Dies ist besonders vorteilhaft für Szenarien, in denen das Kopieren großer Datenmengen unpraktisch oder zu kostspielig wäre.
3. Zeiger-ähnliche Operationen
Während C# traditionell eine sichere High-Level-Sprache ist, führt Span ein gewisses Maß an Low-Level-Speichermanipulation ein, das der Arbeit mit Zeigern in Sprachen wie C oder C++ ähnelt. Entwickler können zeigerähnliche Operationen durchführen, ohne auf die Sicherheit und den verwalteten Charakter von C# zu verzichten.
4. Unveränderliche Natur
Trotz seiner Möglichkeiten für den Speicherzugriff auf niedriger Ebene bleibt C# Span unveränderlich. Das bedeutet, dass es zwar die Manipulation des Speichers erlaubt, aber gleichzeitig die Sicherheit erhöht, indem es unbeabsichtigte Änderungen verhindert.
Beispiel
using System;
class Program
{
void Main()
{
int[] array = { 1, 2, 3, 4, 5 };
// Create a span that points to the entire array
Span<int> span = array;
// Modify the data using the span
span[2] = 10;
// Print the modified array
foreach (var item in array)
{
Console.WriteLine(item);
}
}
}
using System;
class Program
{
void Main()
{
int[] array = { 1, 2, 3, 4, 5 };
// Create a span that points to the entire array
Span<int> span = array;
// Modify the data using the span
span[2] = 10;
// Print the modified array
foreach (var item in array)
{
Console.WriteLine(item);
}
}
}
Imports System
Friend Class Program
Private Sub Main()
Dim array() As Integer = { 1, 2, 3, 4, 5 }
' Create a span that points to the entire array
Dim span As Span(Of Integer) = array
' Modify the data using the span
span(2) = 10
' Print the modified array
For Each item In array
Console.WriteLine(item)
Next item
End Sub
End Class
$vbLabelText $csharpLabel
ReadOnlySpan
Während Span<T> veränderlich ist und Modifikationen an den zugrunde liegenden Daten erlaubt, ist ReadOnlySpan<T> eine unveränderliche Ansicht des Speichers. Sie bietet eine Nur-Lese-Schnittstelle zu einem zusammenhängenden Speicherbereich und eignet sich daher für Szenarien, in denen Sie die Daten nur lesen, aber nicht verändern müssen.
Hier sind einige wichtige Punkte.
1. Schreibgeschützte Ansicht
Wie der Name schon sagt, ermöglicht ReadOnlySpanIhnen, eine schreibgeschützte Ansicht eines Speicherblocks zu erstellen. Dies bedeutet, dass Sie die Elemente nicht über einen ReadOnlySpan<T> ändern können.
2. Darstellung des Speichers
Wie Spanbesitzt ReadOnlySpannicht den Speicher, auf den es verweist. Er bezieht sich auf vorhandenen Speicher und kann auf Arrays, Stack-allocated Memory oder Native Memory verweisen.
3. Leistungsvorteile
Wie Span<T> kann ReadOnlySpan<T> eine bessere Leistung im Vergleich zu traditionellen Sammlungstypen bieten, insbesondere bei der Verarbeitung großer Datenmengen, da es den Bedarf an Kopieren reduziert.
4. Prüfung ohne Grenzen
Wie bei Spanführt ReadOnlySpankeine Bereichsüberprüfung durch. Es liegt in der Verantwortung des Entwicklers, sicherzustellen, dass die Operationen innerhalb der Grenzen des zugrunde liegenden Speichers bleiben.
5. Verwendung mit Array Slicing
ReadOnlySpanunterstützt das Slicing, sodass Sie Teilbereiche erstellen können, die einen Abschnitt des ursprünglichen Speichers referenzieren.
Beispiel
using System;
class Program
{
static void Main()
{
int[] array = { 1, 2, 3, 4, 5 };
// Create a read-only span that points to the entire array
ReadOnlySpan<int> readOnlySpan = array;
// Access and print the data through the read-only span
foreach (var item in readOnlySpan)
{
Console.WriteLine(item);
}
// Note: The following line would result in a compilation error since readOnlySpan is read-only.
// readOnlySpan[2] = 10;
}
}
using System;
class Program
{
static void Main()
{
int[] array = { 1, 2, 3, 4, 5 };
// Create a read-only span that points to the entire array
ReadOnlySpan<int> readOnlySpan = array;
// Access and print the data through the read-only span
foreach (var item in readOnlySpan)
{
Console.WriteLine(item);
}
// Note: The following line would result in a compilation error since readOnlySpan is read-only.
// readOnlySpan[2] = 10;
}
}
Imports System
Friend Class Program
Shared Sub Main()
Dim array() As Integer = { 1, 2, 3, 4, 5 }
' Create a read-only span that points to the entire array
Dim readOnlySpan As ReadOnlySpan(Of Integer) = array
' Access and print the data through the read-only span
For Each item In readOnlySpan
Console.WriteLine(item)
Next item
' Note: The following line would result in a compilation error since readOnlySpan is read-only.
' readOnlySpan[2] = 10;
End Sub
End Class
$vbLabelText $csharpLabel
Es gibt viele verschiedene Möglichkeiten, ReadOnlySpan zu erstellen und mit ihm zu arbeiten. Nachstehend einige Beispiele.
Dim msg As String = "Hello, World!"
Dim span1 As ReadOnlySpan(Of Char) = msg.AsSpan()
' Read-only manipulation
Dim firstChar As Char = span1(0)
Console.WriteLine(firstChar) ' Outputs: H
Dim substringSpan As ReadOnlySpan(Of Char) = spanFromString.Slice(startIndex, length)
$vbLabelText $csharpLabel
3. Übergabe von Substraten an eine Methode
Übergeben Sie ReadOnlySpan<char> als Parameter an die Methode.
void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
// Perform operations on the substring
}
// Usage
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length));
void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
// Perform operations on the substring
}
// Usage
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length));
Private Sub ProcessSubstringfromReadOnlySpan(ByVal substring As ReadOnlySpan(Of Char))
' Perform operations on the substring
End Sub
' Usage
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length))
$vbLabelText $csharpLabel
4. Suche innerhalb einer Zeichenkette
ReadOnlySpanfür die Suche innerhalb einer Zeichenfolge mit IndexOf().
int index = stringSpan.IndexOf('W');
int index = stringSpan.IndexOf('W');
Dim index As Integer = stringSpan.IndexOf("W"c)
$vbLabelText $csharpLabel
5. Verwendung von Memory-Mapped-Dateien
ReadOnlySpankann bei speicherabbildeten Dateien effizienter sein.
using (var memmf = MemoryMappedFile.CreateFromFile("data.bin"))
{
using (var accessor = memmf.CreateViewAccessor())
{
ReadOnlySpan<byte> dataSpan;
accessor.Read(0, out dataSpan);
// Process data directly from the memory-mapped file
ProcessData(dataSpan);
}
}
using (var memmf = MemoryMappedFile.CreateFromFile("data.bin"))
{
using (var accessor = memmf.CreateViewAccessor())
{
ReadOnlySpan<byte> dataSpan;
accessor.Read(0, out dataSpan);
// Process data directly from the memory-mapped file
ProcessData(dataSpan);
}
}
Using memmf = MemoryMappedFile.CreateFromFile("data.bin")
Using accessor = memmf.CreateViewAccessor()
Dim dataSpan As ReadOnlySpan(Of Byte) = Nothing
accessor.Read(0, dataSpan)
' Process data directly from the memory-mapped file
ProcessData(dataSpan)
End Using
End Using
$vbLabelText $csharpLabel
6. Effiziente Manipulation von Zeichenketten
ReadOnlySpankann für eine effiziente Zeichenfolgenmanipulation verwendet werden.
// Replace a character in a substring without creating a new string
spanFromString.Slice(startIndex, length).CopyTo(newSpan);
// Replace a character in a substring without creating a new string
spanFromString.Slice(startIndex, length).CopyTo(newSpan);
' Replace a character in a substring without creating a new string
spanFromString.Slice(startIndex, length).CopyTo(newSpan)
$vbLabelText $csharpLabel
7. Übergabe von Substraten an APIs
Bei der Arbeit mit externen Bibliotheken oder APIs, die mit Zeichenabständen arbeiten.
void ExternalApiMethod(ReadOnlySpan<char> data)
{
// Call the external API with the character span
}
// Usage
ExternalApiMethod(spanFromString.Slice(startIndex, length));
void ExternalApiMethod(ReadOnlySpan<char> data)
{
// Call the external API with the character span
}
// Usage
ExternalApiMethod(spanFromString.Slice(startIndex, length));
Private Sub ExternalApiMethod(ByVal data As ReadOnlySpan(Of Char))
' Call the external API with the character span
End Sub
' Usage
ExternalApiMethod(spanFromString.Slice(startIndex, length))
$vbLabelText $csharpLabel
ReadOnlySpanbietet eine Möglichkeit, effizienter mit Zeichenfolgen zu arbeiten, insbesondere in Szenarien, bei denen Speicherzuweisungen und -kopien minimiert werden sollten. Es ist ein leistungsfähiges Werkzeug zur Optimierung von leistungskritischem Code und kann besonders bei großen Mengen an Zeichenkettendaten von Vorteil sein.
Spannenbegrenzungen
Obwohl Span in C# eine leistungsstarke Funktion mit zahlreichen Vorteilen ist, gibt es auch einige Einschränkungen und Überlegungen, insbesondere im Zusammenhang mit zusammenhängendem und nicht zusammenhängendem Speicher. Lassen Sie uns diese Einschränkungen untersuchen:
1. Zusammenhängende Speicherpuffer
1.1 Keine automatische Speicherverwaltung
Spanverwaltet den Speicher, auf den es zeigt, nicht. Das bedeutet, dass die Verwendung von Span<T> zu undefiniertem Verhalten oder potenziellen Abstürzen führen kann, wenn der zugrunde liegende verwaltete Speicher freigegeben wird oder aus dem Gültigkeitsbereich fällt. Entwickler müssen sicherstellen, dass der zugrundeliegende Speicher noch gültig ist, wenn ein Span<T> verwendet wird.
1.2 Keine Müllabfuhr
Da Span<T> keinen Speicher besitzt, unterliegt es nicht der Speicherbereinigung. Daher muss man vorsichtig sein, wenn man mit speicherplatzallokiertem Speicher oder Speicher mit einer kürzeren Lebensdauer als der Span<T> selbst arbeitet.
1.3 Bounds Checking ist deaktiviert
Spanund ReadOnlySpanführen standardmäßig keine Bereichsüberprüfung durch. Dies kann dazu führen, dass auf ungültige Speicherplätze zugegriffen wird, wenn nicht sorgfältig damit umgegangen wird. Entwickler müssen manuell sicherstellen, dass die Operationen auf einem Spaninnerhalb der Grenzen des zugrunde liegenden Speichers bleiben.
1.4 Keine Unterstützung für nicht zusammenhängenden Speicher
Span<T> ist dafür ausgelegt, mit zusammenhängendem Speicher zu arbeiten. Wenn Sie über nicht zusammenhängenden Speicher verfügen oder komplexere Datenstrukturen darstellen müssen, ist Spanmöglicherweise nicht die geeignetste Wahl.
1.5 Es werden nicht alle Operationen unterstützt
Während Span<T> viele gängige Operationen wie Schneiden, Indexierung und Iteration unterstützt, werden nicht alle Operationen unterstützt. Zum Beispiel können Sie ein Spannicht ändern, und bestimmte Operationen, die eine Änderung der Länge des zugrunde liegenden Speichers beinhalten, sind nicht erlaubt.
1.6 Eingeschränkte Plattformkompatibilität
Während Span<T> Teil von .NET Standard und .NET Core ist, ist es möglicherweise nicht auf allen Plattformen oder Umgebungen verfügbar. Es ist entscheidend, sicherzustellen, dass Ihre Zielplattform Spanunterstützt, wenn Sie planen, es in Ihrem Code zu verwenden.
2. Nicht zusammenhängende Speicherpuffer
2.1 Eingeschränkte Unterstützung für nicht zusammenhängenden Speicher
ReadOnlySpanist in erster Linie dafür konzipiert, nahtlos mit zusammenhängenden Speicherblöcken oder Puffern zu arbeiten. Es ist möglicherweise nicht die beste Wahl für Szenarien, in denen nicht zusammenhängende Speicherpuffer oder Strukturen mit Lücken im Speicher betroffen sind.
2.2 Strukturelle Beschränkungen
Bestimmte Datenstrukturen oder Szenarien, die auf nicht zusammenhängendem Speicher basieren, passen möglicherweise nicht gut zu ReadOnlySpan<T>. Zum Beispiel könnten Datenstrukturen wie verkettete Listen oder Graphstrukturen aufgrund des zusammenhängenden Speicherbedarfs von ReadOnlySpan<T> nicht gut geeignet sein.
2.3 Komplexe Zeigeroperationen
In Situationen, die nicht zusammenhängenden Speicher betreffen, insbesondere solche, die komplizierte Zeigerarithmetik erfordern, bietet ReadOnlySpan<T> möglicherweise nicht die gleiche Kontrolle und Flexibilität auf niedriger Ebene wie rohe Zeiger in Sprachen wie C++. In solchen Fällen könnte die Verwendung von unsicherem Code mit Zeigern sinnvoller sein.
2.4 Fehlende direkte Unterstützung in einigen APIs
Ähnlich wie zusammenhängender Speicher ist es wichtig zu beachten, dass nicht alle APIs oder Bibliotheken möglicherweise direkt nicht-zusammenhängenden Speicher unterstützen, der durch ReadOnlySpanrepräsentiert wird. Die Anpassung an solche Szenarien kann zusätzliche Zwischenschritte oder Konvertierungen erforderlich machen, um die Kompatibilität zu gewährleisten.
Span und nicht verwalteter Speicher
In C# kann Span effektiv mit nicht verwaltetem Speicher verwendet werden, um speicherbezogene Operationen auf kontrollierte und effiziente Weise durchzuführen. Unverwalteter Speicher bezieht sich auf Speicher, der nicht vom Garbage Collector der .NET-Laufzeitumgebung verwaltet wird, und beinhaltet oft die Verwendung von nativen Speicherzuweisungen und -freigaben. Hier ist, wie Span kann mit unmanaged Speicher in C# verwendet werden.
Zuweisung von nicht verwaltetem Speicher
Um nicht verwalteten Speicher zuzuweisen, können Sie die Klasse System.Runtime.InteropServices.MemoryMarshal verwenden. Die Marshal.AllocHGlobal-Methode weist Speicher zu und gibt einen Zeiger auf den zugewiesenen Block zurück. Der zugewiesene Speicher oder die Speicheradresse wird in einem unmanagedMemory-Zeiger gehalten und hat Lese- und Schreibzugriff. Auf die zusammenhängenden Bereiche des Speichers kann leicht zugegriffen werden.
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Create a Span from the unmanaged memory
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Use the Span as needed...
// Don't forget to free the unmanaged memory when done
Marshal.FreeHGlobal(unmanagedMemory);
}
}
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Create a Span from the unmanaged memory
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Use the Span as needed...
// Don't forget to free the unmanaged memory when done
Marshal.FreeHGlobal(unmanagedMemory);
}
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
Shared Sub Main()
Const bufferSize As Integer = 100
Dim unmanagedMemory As IntPtr = Marshal.AllocHGlobal(bufferSize)
' Create a Span from the unmanaged memory
Dim span As New Span(Of Byte)(unmanagedMemory.ToPointer(), bufferSize)
' Use the Span as needed...
' Don't forget to free the unmanaged memory when done
Marshal.FreeHGlobal(unmanagedMemory)
End Sub
End Class
$vbLabelText $csharpLabel
Im obigen Quellcode allokieren wir einen Block von nicht verwaltetem Speicher mithilfe von Marshal.AllocHGlobal und erstellen dann ein Spanunter Verwendung des Zeigers, der aus dem nicht verwalteten Speicher erhalten wurde. Dadurch können wir mit nicht verwaltetem Speicher arbeiten, indem wir die bekannte Span-API verwenden. Es ist wichtig zu wissen, dass Sie bei der Arbeit mit nicht verwaltetem Speicher für die Verwaltung der Zuweisung und Freigabe des Speichers verantwortlich sind.
Kopieren von Daten in und aus nicht verwaltetem Speicher
Span bietet Methoden wie Slice, CopyTo und ToArray, die für das effiziente Kopieren von Daten zwischen verwaltetem und nicht verwaltetem Speicher verwendet werden können.
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
// Managed array to copy data from
int[] sourceArray = { 1, 2, 3, 4, 5 };
// Allocate unmanaged memory for the destination data
IntPtr destinationPointer = MemoryMarshal.Allocate<int>(sourceArray.Length);
try
{
// Create a Span<int> from the source array
Span<int> sourceSpan = sourceArray;
// Create a Span<int> from the allocated unmanaged memory
Span<int> destinationSpan = MemoryMarshal.Cast<int, byte>(destinationPointer, sourceArray.Length);
// Copy data from the source Span<int> to the destination Span<int>
sourceSpan.CopyTo(destinationSpan);
// Print the values in the destination memory
Console.WriteLine("Values in the destination memory:");
foreach (var value in destinationSpan)
{
Console.Write($"{value} ");
}
}
finally
{
// Deallocate the unmanaged memory when done
MemoryMarshal.Free(destinationPointer);
}
}
}
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
// Managed array to copy data from
int[] sourceArray = { 1, 2, 3, 4, 5 };
// Allocate unmanaged memory for the destination data
IntPtr destinationPointer = MemoryMarshal.Allocate<int>(sourceArray.Length);
try
{
// Create a Span<int> from the source array
Span<int> sourceSpan = sourceArray;
// Create a Span<int> from the allocated unmanaged memory
Span<int> destinationSpan = MemoryMarshal.Cast<int, byte>(destinationPointer, sourceArray.Length);
// Copy data from the source Span<int> to the destination Span<int>
sourceSpan.CopyTo(destinationSpan);
// Print the values in the destination memory
Console.WriteLine("Values in the destination memory:");
foreach (var value in destinationSpan)
{
Console.Write($"{value} ");
}
}
finally
{
// Deallocate the unmanaged memory when done
MemoryMarshal.Free(destinationPointer);
}
}
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
Shared Sub Main()
' Managed array to copy data from
Dim sourceArray() As Integer = { 1, 2, 3, 4, 5 }
' Allocate unmanaged memory for the destination data
Dim destinationPointer As IntPtr = MemoryMarshal.Allocate(Of Integer)(sourceArray.Length)
Try
' Create a Span<int> from the source array
Dim sourceSpan As Span(Of Integer) = sourceArray
' Create a Span<int> from the allocated unmanaged memory
Dim destinationSpan As Span(Of Integer) = MemoryMarshal.Cast(Of Integer, Byte)(destinationPointer, sourceArray.Length)
' Copy data from the source Span<int> to the destination Span<int>
sourceSpan.CopyTo(destinationSpan)
' Print the values in the destination memory
Console.WriteLine("Values in the destination memory:")
For Each value In destinationSpan
Console.Write($"{value} ")
Next value
Finally
' Deallocate the unmanaged memory when done
MemoryMarshal.Free(destinationPointer)
End Try
End Sub
End Class
$vbLabelText $csharpLabel
In diesem Beispiel:
MemoryMarshal.Allocate(sourceArray.Length) reserviert nicht verwalteten Speicher für die Zieldaten. MemoryMarshal.Cast<int, byte>(destinationPointer, sourceArray.Length) erstellt einen Spanaus dem zugewiesenen nicht verwalteten Speicher. Die Methode sourceSpan.CopyTo(destinationSpan) kopiert die Daten aus dem verwalteten Array in den nicht verwalteten Speicher. Die Werte im Zielspeicher werden ausgedruckt, um den Kopiervorgang zu überprüfen. Die Methode MemoryMarshal.Free(destinationPointer) wird verwendet, um den nicht verwalteten Speicher nach der Verwendung freizugeben.
Unsicheren Code verwenden
Wenn Sie mit nicht verwaltetem Speicher arbeiten, können Sie auch unsicheren Code mit Zeigern verwenden. In solchen Fällen können Sie einen Zeiger aus dem Span mit der Unsafe.AsPointer()-Methode erhalten.
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Create a Span from the unmanaged memory
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Use unsafe code to work with pointers
// ref t
unsafe
{
byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
// Use the pointer as needed...
}
// Don't forget to free the unmanaged memory when done
Marshal.FreeHGlobal(unmanagedMemory);
}
}
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Create a Span from the unmanaged memory
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Use unsafe code to work with pointers
// ref t
unsafe
{
byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
// Use the pointer as needed...
}
// Don't forget to free the unmanaged memory when done
Marshal.FreeHGlobal(unmanagedMemory);
}
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
Shared Sub Main()
Const bufferSize As Integer = 100
Dim unmanagedMemory As IntPtr = Marshal.AllocHGlobal(bufferSize)
' Create a Span from the unmanaged memory
Dim span As New Span(Of Byte)(unmanagedMemory.ToPointer(), bufferSize)
' Use unsafe code to work with pointers
' ref t
'INSTANT VB TODO TASK: C# 'unsafe' code is not converted by Instant VB:
' unsafe
' {
' byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
' ' Use the pointer as needed...
' }
' Don't forget to free the unmanaged memory when done
Marshal.FreeHGlobal(unmanagedMemory)
End Sub
End Class
$vbLabelText $csharpLabel
In diesem Beispiel verwenden wir die Methode Unsafe.AsPointer, um einen Zeiger von Span zu erhalten. Dies ermöglicht uns die Verwendung von unsicherem Code, wenn wir direkt mit Zeigern arbeiten.
Denken Sie daran, dass es bei der Arbeit mit nicht verwaltetem Speicher wichtig ist, die Zuweisung und Freigabe richtig zu verwalten, um Speicherlecks zu vermeiden. Verwenden Sie immer geeignete Methoden, wie beispielsweise Marshal.FreeHGlobal(), um nicht verwalteten Speicher freizugeben. Seien Sie außerdem vorsichtig bei der Verwendung von unsicherem Code, da dieser bei unsachgemäßer Handhabung potenzielle Sicherheitsrisiken bergen kann.
Span und asynchrone Methodenaufrufe
Die Verwendung von Span in Verbindung mit asynchronen Methodenaufrufen in C# ist eine leistungsstarke Kombination, vor allem wenn es um große Datenmengen oder E/A-Operationen geht. Ziel ist es, asynchrone Operationen ohne unnötiges Kopieren von Daten effizient abzuwickeln. Lassen Sie uns untersuchen, wie Sie Span in asynchronen Szenarien nutzen können:
Asynchrone I/O-Operationen:
Beim Umgang mit asynchronen I/O-Operationen, wie dem Lesen oder Schreiben von Daten in einen Stream, können Sie Memory<T> oder Span<T> verwenden, um effizient mit den Daten zu arbeiten, ohne zusätzliche Puffer zu erstellen.
async Task ProcessDataAsync(Stream stream)
{
const int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (true)
{
int bytesRead = await stream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Process the data using Span without unnecessary copying
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
void ProcessData(Span<byte> data)
{
// Perform operations on the data
}
async Task ProcessDataAsync(Stream stream)
{
const int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (true)
{
int bytesRead = await stream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Process the data using Span without unnecessary copying
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
void ProcessData(Span<byte> data)
{
// Perform operations on the data
}
Async Function ProcessDataAsync(ByVal stream As Stream) As Task
Const bufferSize As Integer = 4096
Dim buffer(bufferSize - 1) As Byte
Do
Dim bytesRead As Integer = Await stream.ReadAsync(buffer.AsMemory())
If bytesRead = 0 Then
Exit Do
End If
' Process the data using Span without unnecessary copying
ProcessData(buffer.AsSpan(0, bytesRead))
Loop
End Function
Private Sub ProcessData(ByVal data As Span(Of Byte))
' Perform operations on the data
End Sub
$vbLabelText $csharpLabel
In diesem Beispiel liest die Methode ReadAsync asynchron Daten aus einem Stream in den Puffer. Die Methode ProcessData verarbeitet die Daten dann direkt aus dem Span, ohne sie in einen anderen Puffer zu kopieren.
2. Asynchrone Dateioperationen:
Ähnlich wie bei E/A-Operationen können Sie bei asynchronen Dateioperationen Span verwenden, um Daten ohne zusätzliches Kopieren effizient zu verarbeiten.
async Task ProcessFileAsync(string filePath)
{
const int bufferSize = 4096;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[bufferSize];
while (true)
{
int bytesRead = await fileStream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Process the data using Span without unnecessary copying
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
}
void ProcessData(Span<byte> data)
{
// Perform operations on the data
}
async Task ProcessFileAsync(string filePath)
{
const int bufferSize = 4096;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[bufferSize];
while (true)
{
int bytesRead = await fileStream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Process the data using Span without unnecessary copying
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
}
void ProcessData(Span<byte> data)
{
// Perform operations on the data
}
Async Function ProcessFileAsync(ByVal filePath As String) As Task
Const bufferSize As Integer = 4096
Using fileStream As New FileStream(filePath, FileMode.Open, FileAccess.Read)
Dim buffer(bufferSize - 1) As Byte
Do
Dim bytesRead As Integer = Await fileStream.ReadAsync(buffer.AsMemory())
If bytesRead = 0 Then
Exit Do
End If
' Process the data using Span without unnecessary copying
ProcessData(buffer.AsSpan(0, bytesRead))
Loop
End Using
End Function
Private Sub ProcessData(ByVal data As Span(Of Byte))
' Perform operations on the data
End Sub
$vbLabelText $csharpLabel
Hier liest die Methode ReadAsync Daten aus einem Dateistream in den Puffer, und die Methode ProcessData verarbeitet die Daten direkt aus dem Span.
3. Asynchrone Aufgabenverarbeitung:
Wenn Sie mit asynchronen Aufgaben arbeiten, die Daten produzieren oder konsumieren, können Sie Memory<T> oder Span<T> verwenden, um unnötige Kopien zu vermeiden.
async Task<int> ProcessDataAsync(int[] data)
{
// Asynchronous processing of data
await Task.Delay(1000);
// Returning the length of the processed data
return data.Length;
}
async Task Main()
{
int[] inputData = Enumerable.Range(1, 1000).ToArray();
// Process the data asynchronously without copying
int processedLength = await ProcessDataAsync(inputData.AsMemory());
Console.WriteLine($"Processed data length: {processedLength}");
}
async Task<int> ProcessDataAsync(int[] data)
{
// Asynchronous processing of data
await Task.Delay(1000);
// Returning the length of the processed data
return data.Length;
}
async Task Main()
{
int[] inputData = Enumerable.Range(1, 1000).ToArray();
// Process the data asynchronously without copying
int processedLength = await ProcessDataAsync(inputData.AsMemory());
Console.WriteLine($"Processed data length: {processedLength}");
}
Async Function ProcessDataAsync(ByVal data() As Integer) As Task(Of Integer)
' Asynchronous processing of data
Await Task.Delay(1000)
' Returning the length of the processed data
Return data.Length
End Function
Async Function Main() As Task
Dim inputData() As Integer = Enumerable.Range(1, 1000).ToArray()
' Process the data asynchronously without copying
Dim processedLength As Integer = Await ProcessDataAsync(inputData.AsMemory())
Console.WriteLine($"Processed data length: {processedLength}")
End Function
$vbLabelText $csharpLabel
In diesem Beispiel verarbeitet die Methode ProcessDataAsync die Daten asynchron und gibt die Länge der verarbeiteten Daten zurück, ohne dass zusätzliche Kopien erforderlich sind.
Einführung in IronPDF
IronPDF-Bibliothek Übersicht ist die neueste C#-PDF-Bibliothek von Iron Software, die verwendet werden kann, um mit C#-Code dynamisch wunderschöne PDF-Dokumente zu erstellen. IronPDF bietet eine Vielzahl von Funktionen, wie z. B. PDF-Erzeugung aus HTML, Konvertierung von HTML-Inhalten in PDF, Zusammenführen oder Teilen von PDF-Dateien usw.
Die Hauptfunktion von IronPDF ist seine HTML-zu-PDF-Funktionalität, die Layouts und Stile bewahrt. Es kann PDFs aus Webinhalten generieren und eignet sich daher hervorragend für Berichte, Rechnungen und Dokumentationen. Dieses Tool unterstützt die Umwandlung von HTML-Dateien, URLs und HTML-Strings in PDF-Dateien.
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
Einrichtung
IronPDF kann über den NuGet-Paketmanager für IronPDF Konsole oder über den Visual Studio-Paketmanager installiert werden.
dotnet add package IronPdf
// Or
Install-Package IronPdf
dotnet add package IronPdf
// Or
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'dotnet add package IronPdf Install-Package IronPdf
$vbLabelText $csharpLabel
using System;
class Program
{
static void Main()
{
Console.WriteLine("Generating PDF using IronPDF.");
var displayFirstName = "<p>First Name is Joe</p>".AsSpan();
var displayLastName = "<p>First Name is Doe</p>".AsSpan();
var displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan();
var start = @"<!DOCTYPE html>
<html>
<body>".AsSpan();
var end = @"<!DOCTYPE html>
<html>
<body>";
var content = string.Concat(start, displayFirstName, displayLastName, string.Concat(displayAddress, end));
var pdfDocument = new ChromePdfRenderer();
pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf");
}
}
using System;
class Program
{
static void Main()
{
Console.WriteLine("Generating PDF using IronPDF.");
var displayFirstName = "<p>First Name is Joe</p>".AsSpan();
var displayLastName = "<p>First Name is Doe</p>".AsSpan();
var displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan();
var start = @"<!DOCTYPE html>
<html>
<body>".AsSpan();
var end = @"<!DOCTYPE html>
<html>
<body>";
var content = string.Concat(start, displayFirstName, displayLastName, string.Concat(displayAddress, end));
var pdfDocument = new ChromePdfRenderer();
pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf");
}
}
Imports System
Friend Class Program
Shared Sub Main()
Console.WriteLine("Generating PDF using IronPDF.")
Dim displayFirstName = "<p>First Name is Joe</p>".AsSpan()
Dim displayLastName = "<p>First Name is Doe</p>".AsSpan()
Dim displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan()
Dim start = "<!DOCTYPE html>
<html>
<body>".AsSpan()
Dim [end] = "<!DOCTYPE html>
<html>
<body>"
Dim content = String.Concat(start, displayFirstName, displayLastName, String.Concat(displayAddress, [end]))
Dim pdfDocument = New ChromePdfRenderer()
pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf")
End Sub
End Class
$vbLabelText $csharpLabel
In diesem Beispiel verwenden wir Span zusammen mit IronPDF, um ein PDF-Dokument zu erstellen.
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'"IronPdf.LicenseKey": "your license key"
$vbLabelText $csharpLabel
Geben Sie Ihre E-Mail-Adresse an, um eine Testlizenz zu erhalten.
Schlussfolgerung
Span<T> in C# bietet eine leistungsstarke und effiziente Möglichkeit, mit Speicher zu arbeiten und bietet Vorteile in Bezug auf Leistung und Flexibilität. Die nicht-besitzende, zusammenhängende Natur macht es besonders geeignet für Szenarien, in denen die Minimierung von Speicherzuweisungen und -kopien entscheidend ist. Durch den Einsatz von Span können Entwickler eine bessere Leistung in einer Vielzahl von Anwendungen erzielen, die von der Zeichenkettenmanipulation bis zur leistungsstarken numerischen Verarbeitung reichen. Indem Entwickler die Funktionen von Span<T> verstehen und seine Einschränkungen berücksichtigen, können sie es sicher und effizient für verschiedene Aufgaben der Speicherverwaltung einsetzen. Zusammen mit der IronPDF-Bibliotheksübersicht kann es verwendet werden, um beeindruckende PDF-Dokumente ohne await- und yield-Grenzen zu erstellen.
Chipego hat eine natürliche Fähigkeit zum Zuhören, die ihm hilft, Kundenprobleme zu verstehen und intelligente Lösungen anzubieten. Er trat dem Iron Software-Team 2023 bei, nachdem er einen Bachelor of Science in Informationstechnologie erworben hatte. IronPDF und IronOCR sind die beiden Produkte, auf die sich Chipego konzentriert hat, aber sein Wissen über alle Produkte wächst täglich, da er neue Wege findet, Kunden zu unterstützen. Er genießt die Zusammenarbeit bei Iron Software, da Teammitglieder aus dem gesamten Unternehmen ihre unterschiedlichen Erfahrungen einbringen und so zu effektiven, innovativen Lösungen beitragen. Wenn Chipego nicht an seinem Schreibtisch sitzt, kann man ihn oft bei einem guten Buch oder beim Fußballspielen antreffen.
< PREVIOUS C# IDE (Wie es für Entwickler funktioniert)
NÄCHSTES > Opentelemetry C# (Wie es für Entwickler funktioniert)