<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>reportprogress Archive - Robert Skibbe</title>
	<atom:link href="https://robbelroot.de/blog/tag/reportprogress/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>alias RobbelRoot – Freelance Full Stack Developer .NET</description>
	<lastBuildDate>Wed, 25 Mar 2026 11:04:43 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://robbelroot.de/wp-content/uploads/2020/12/cropped-favicon-32x32.png</url>
	<title>reportprogress Archive - Robert Skibbe</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Die ultimative VB.NET Background Worker Anleitung in 2026</title>
		<link>https://robbelroot.de/blog/backgroundworker-beispiel-in-vb-net/</link>
					<comments>https://robbelroot.de/blog/backgroundworker-beispiel-in-vb-net/#comments</comments>
		
		<dc:creator><![CDATA[Robert Skibbe]]></dc:creator>
		<pubDate>Sun, 04 Sep 2022 19:24:51 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Visual Basic .NET]]></category>
		<category><![CDATA[Visual Basic .NET Problemlösungen]]></category>
		<category><![CDATA[async]]></category>
		<category><![CDATA[background]]></category>
		<category><![CDATA[backgroundworker]]></category>
		<category><![CDATA[cancel]]></category>
		<category><![CDATA[multithreading]]></category>
		<category><![CDATA[parameter]]></category>
		<category><![CDATA[pause]]></category>
		<category><![CDATA[progress]]></category>
		<category><![CDATA[reportprogress]]></category>
		<category><![CDATA[runworkerasync]]></category>
		<category><![CDATA[stop]]></category>
		<category><![CDATA[task]]></category>
		<category><![CDATA[thread]]></category>
		<category><![CDATA[threading]]></category>
		<category><![CDATA[vb.net]]></category>
		<category><![CDATA[vbnet]]></category>
		<category><![CDATA[worker]]></category>
		<guid isPermaLink="false">https://robbelroot.de/?p=1858</guid>

					<description><![CDATA[<p>Intro In diesem ausführlichen Backgroundworker Beispiel, zeige ich dir alles, was Du über Ihn wissen musst: Die grundsätzliche Funktionalität, Tipps &#38; Tricks und mehr. Der Code steht dir sowohl in VB.NET als auch in C# zur Verfügung Ebenso relevant wie die Funktionsweise des Backgroundworkers, ist natürlich auch, ob es im &#8230;</p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/backgroundworker-beispiel-in-vb-net/">Die ultimative VB.NET Background Worker Anleitung in 2026</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild-.jpg"><img fetchpriority="high" decoding="async" width="1024" height="624" src="https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild--1024x624.jpg" alt="BackgroundWorker Beispiel in VB.NET – Der Handwerker im Hintergrund" class="wp-image-1861" srcset="https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild--1024x624.jpg 1024w, https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild--300x183.jpg 300w, https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild--768x468.jpg 768w, https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild--700x427.jpg 700w, https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild--332x202.jpg 332w, https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild--268x164.jpg 268w, https://robbelroot.de/wp-content/uploads/2021/06/net-Backgroundworker-Beispiel-Handwerker-Bild-.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">BackgroundWorker Beispiel in VB.NET – Der Handwerker im Hintergrund</figcaption></figure>






<h2 class="wp-block-heading">Intro</h2>



<p>In diesem ausführlichen <strong>Backgroundworker Beispiel</strong>, zeige ich dir alles, was Du über Ihn wissen musst: Die grundsätzliche Funktionalität, Tipps &amp; Tricks und mehr. Der Code steht dir sowohl in VB.NET als auch in C# zur Verfügung</p>



<p><strong>Ebenso relevant wie</strong> die <strong>Funktionsweise </strong>des Backgroundworkers, ist natürlich auch, <strong>ob es</strong> im .NET Framework <strong>mittlerweile modernere Alternativen</strong> <strong>gibt</strong>.</p>



<p>So wie die Zeit, <strong>bleibt </strong>natürlich auch das <strong>NET Framework nicht stehen</strong> und <strong>alte Technologien</strong>, bzw. Teile des Frameworks werden <strong>durch neuere</strong> und ggf. <strong>bessere </strong>– oder einfachere – <strong>Methoden erweitert</strong>.</p>



<h2 class="wp-block-heading">Multithreading mit Backgroundworker in .NET</h2>



<h3 class="wp-block-heading">Wofür bzw. was ist ein BGW?</h3>



<p>Zuerst einmal wirst du dich vermutlich bei deinem <strong>ersten Kontakt</strong> mit einem <strong>Backgroundworker </strong>– <strong>kurz BGW</strong> – fragen, <strong>wozu</strong> du Ihn <strong>brauchst</strong>.</p>



<p>Der <strong>Backgroundworker </strong>ist <strong>wie der Name schon</strong> <strong>vermuten lässt </strong>dazu da, <strong>Aufgaben im Hintergrund abzuarbeiten</strong>.</p>



<p><strong>Stelle dir</strong> den BGW wie <strong>einen Handwerker vor</strong>, den du <strong>mit etwas beauftragst</strong>, was etwas mehr Zeit in Anspruch nimmt.</p>



<p><strong>Solange er</strong> z. B. den <strong>Rasen mäht</strong>, oder die <strong>Spülmaschine repariert</strong>, hast <strong>du hingegen Zeit für andere Sachen</strong>.</p>



<h3 class="wp-block-heading">Praxisbeispiele</h3>



<p><strong>Beispiele aus der Praxis</strong> wären eventuell:</p>



<ul class="wp-block-list">
<li><strong>Zugriffe auf </strong>die <strong>Festplatte </strong>für die <strong>Auflistung von Verzeichnissen</strong> und <strong>Dateien</strong></li>



<li>oder etwa das <strong>scannen von Ports </strong>einer gewissen <strong>IP-Adresse</strong>.</li>
</ul>



<p><strong>Wenn </strong>der <strong>Handwerker </strong>– ergo <strong>der BGW</strong> – seine <strong>Arbeit erledigt</strong> hat, kann <strong>er es</strong> dir <strong>mitteilen</strong>.</p>



<p>Alternativ kann er auch <strong>zwischendurch </strong>einen kleinen <strong>Status </strong>darüber <strong>liefern</strong>, wie weit er mit seiner Arbeit ist.</p>



<p><strong>Während </strong>der <strong>Handwerker </strong>seine <strong>Arbeit verrichtet</strong>, könntest du Ihm natürlich auch ein <strong>Glas Wasser anbieten</strong> und ihn <strong>pausieren lassen</strong>.</p>



<hr class="wp-block-separator has-css-opacity"/>



<h3 class="wp-block-heading">Kein Genuss für Anfänger</h3>



<p>Zugegebenermaßen ist die <strong>Verwendung des Backgroundworkers</strong> vor Allem <strong>für Anfänger</strong> <strong>nicht gerade ein Genuss</strong>, geschweige denn einfach. So habe ich es auf jeden Fall <strong>bei </strong>mehreren <strong>meiner Schüler</strong>, bzw. <strong>aus dem Netz</strong> und früher auch am eigenen Leib erlebt.</p>



<p>Mit <strong>ausreichend Erfahrung</strong> kann sich ein <strong>fortgeschrittener Programmierer</strong> natürlich die <strong>jeweiligen Puzzleteile </strong>für einen Backgroundworker <strong>zusammenfügen</strong>.</p>



<p>Andersherum schlagen sich besonders <strong>Anfänger</strong> <strong>mühsam mit </strong>den hier genannten <strong>Fragen herum</strong>. Dabei geht es <strong>hauptsächlich</strong> um <strong>Themen </strong>wie die <strong>Übergabe von Parametern</strong> an den Backgroundworker. Ein weiteres Beispiel wäre die <strong>Anzeige eines Status</strong> in z. B. einer <strong>ProgressBar</strong>.</p>



<h3 class="wp-block-heading">Gängige Fragen</h3>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2021/09/Haeufige-Backgroundworker-Fragen.jpg"><img decoding="async" width="640" height="320" src="https://robbelroot.de/wp-content/uploads/2021/09/Haeufige-Backgroundworker-Fragen.jpg" alt="Häufige Backgroundworker Fragen" class="wp-image-5986" title="Häufige Backgroundworker Fragen"/></a><figcaption class="wp-element-caption">Häufige Backgroundworker Fragen</figcaption></figure>



<p>In meinem <strong>Backgroundworker-Beispiel</strong> findest du <strong>Code</strong> und Erklärungen, Welche die <strong>Antworten auf folgende Fragen</strong> liefern:</p>



<ul class="wp-block-list">
<li><strong>Wofür </strong>brauche ich <strong>einen Backgroundworker</strong>?</li>



<li>Wie <strong>pausiere </strong>ich einen <strong>Backgroundworker</strong> (pause)?</li>



<li>Wie <strong>breche </strong>ich einen <strong>Backgroundworker ab</strong> (cancel)?</li>



<li>Wie kann ein <strong>Backgroundworker </strong>einen <strong>Fortschritt wiedergeben</strong> (report)?</li>



<li>Wie kann ich dem <strong>Backgroundworker </strong>einen <strong>Parameter übergeben</strong>?</li>



<li>Wie <strong>übergebe </strong>ich dem Backgroundworker <strong>mehrere Parameter</strong>?</li>



<li>Wie zeige ich mit Hilfe des <strong>Backgroundworkers </strong>den <strong>Status in</strong> einer <strong>ProgressBar – </strong>Thread und GUI sicher – <strong>an</strong>?</li>



<li>Gibt es <strong>modernere Alternativen </strong>zum <strong>Backgroundworker</strong>?</li>
</ul>



<p>Die <strong>Antworten auf diese Fragen</strong> versuche ich <strong>durch den Code zu veranschaulichen</strong> und letztendlich zu <strong>erklären</strong>.</p>



<h2 class="wp-block-heading">Backgroundworker Beispiel – Der Code</h2>



<h3 class="wp-block-heading">Backgroundworker deklarieren</h3>



<p><strong>Definiere </strong>den <strong>Backgroundworker innerhalb der Form</strong>, also <strong>innerhalb der Klasse</strong>. <strong>Achte darauf</strong>, dass du ihn <strong>außerhalb der Methoden</strong> also als Member der Klasse positionierst.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="feld-deklaration">Private WithEvents Worker As BackgroundWorker</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="feld-deklaration">private BackgroundWorker Worker;</pre>



<h4 class="wp-block-heading">Private oder Dim</h4>



<p><strong>Zuerst </strong>verwenden wir das <strong>&#8222;Private&#8220;-Schlüsselwort</strong>. Es stellt schon den <strong>ersten Unterschied</strong> zu vielerlei online auffindbaren <strong>Code </strong>dar.</p>



<p>&#8222;<strong>Private</strong>&#8220; ist ein <strong>Zugriffsmodifizierer</strong>, Welcher <strong>neben Anderen</strong> und <strong>im Gegensatz</strong> zu dem häufig verwendeten &#8222;<strong>Dim</strong>&#8220; auf <strong>Klasssenebene</strong> verwendet wird.</p>



<p>&#8222;<strong>Dim</strong>&#8220; hat zwar den <strong>selben Effekt</strong>, also es würde <strong>auch in diesem</strong> Fall den <strong>Worker </strong>als <strong>Private </strong>kennzeichnen. <strong>Leider </strong>ist es aber meiner Meinung nach <strong>unsauber</strong>. Es dient <strong>nur zur Deklaration</strong> bzw. <strong>Initialisierung </strong>einer <strong>lokalen Variable</strong> in z. B. einem Konstruktor oder einer &#8222;normalen&#8220; Methode.</p>



<h4 class="wp-block-heading">WithEvents</h4>



<p>Das <strong>&#8222;WithEvents&#8220;-Schlüsselwort</strong> gibt an, dass <strong>ein oder mehrere</strong> auf Klassen- oder Modulebene deklarierte <strong>Elemente, Ereignisse hervorrufen</strong> können.</p>



<p>Im Falle des <strong>Backgroundworkers </strong>sind das <strong>unter Anderem</strong> das &#8222;<strong>ProgressChanged</strong>&#8222;- und das &#8222;<strong>RunWorkerCompleted</strong>&#8222;-<strong>Ereignis</strong>.</p>



<h4 class="wp-block-heading">Worker</h4>



<p>Das ist einfach <strong>nur der Name</strong>, mit dessen Hilfe wir <strong>den jeweiligen Backgroundworker</strong> – auf Klassenebene – im Code <strong>ansprechen </strong>und <strong>verwenden </strong>können.</p>



<h4 class="wp-block-heading">As BackgroundWorker </h4>



<p>Die <strong>&#8222;As&#8220;-Klausel</strong> bzw. das <strong>&#8222;As&#8220;-Schlüsselwort</strong> dient <strong>in </strong>der <strong>Deklaration </strong>als <strong>&#8222;Zuweisungsoperator&#8220;</strong> für einen <strong>Datentyp</strong>. Praktisch übersetze heißt das dann einfach: &#8222;<strong>Du bist vom Typ X</strong>&#8222;. In <strong>unserem Fall</strong>: &#8222;Du bist <strong>vom Datentyp BackgroundWorker</strong>&#8222;.</p>



<p>Das ist natürlich <strong>besonders durch</strong> das <strong>&#8222;WithEvents&#8220;-Schlüsselwort wichtig</strong>, <strong>damit </strong>&#8222;unser <strong>Code </strong>auch <strong>weiß</strong>&#8220; <strong>von wem</strong>, <strong>welche Ereignisse</strong> ausgelöst werden können.</p>



<h4 class="wp-block-heading">New</h4>



<p><strong>Häufig findet man</strong> im <strong>online </strong>recherchierten <strong>Code </strong>so etwas wie:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="feld-mit-new">Private WithEvents Worker As New BackgroundWorker</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="feld-mit-new">private BackgroundWorker Worker = new BackgroundWorker();</pre>



<p><strong>Davon halte ich</strong> ebenfalls <strong>nichts</strong>, da es sich auch <strong>hier unsauber</strong> anfühlt. <strong>Instanziierungen sollten </strong>im dafür <strong>vorgesehenen Schritt</strong> des – ich nenne es mal – <strong>Lebenszyklus</strong> durchgeführt werden.</p>



<p>Das wäre meines Erachtens nach <strong>im Konstruktor der jeweiligen Klasse.</strong> <strong>Dort </strong>werden – <strong>ggf</strong>. auch durch <strong>weitere Methoden</strong> (Subs) – die <strong>verschiedenen Objekte</strong> <strong>auf </strong>ihren <strong>Einsatz vorbereitet</strong>.</p>



<h3 class="wp-block-heading">Backgroundworker vorbereiten</h3>



<p><strong>Im Konstruktor der Form</strong>, Welchen wir durch das Tippen von s-u-b Leerzeichen n-e-w und Enter generieren können:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="konstruktor-vorbereitung">Sub New()

    ' Dieser Aufruf ist für den Designer erforderlich.
    InitializeComponent()

    ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.

End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="konstruktor-vorbereitung">public Form1()
{

    // Dieser Aufruf ist für den Designer erforderlich.
    InitializeComponent();

    // Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.

}</pre>



<p>fügen wir nun <strong>eine Methode</strong> namens &#8222;InitializeBackgroundWorker&#8220; hinzu. <strong>Anschließend erstellen</strong> wir Diese, <strong>oder lassen Diese via</strong> Visual Studios <strong>Hilfsfunktionen generieren</strong>.</p>



<h4 class="wp-block-heading">Hilfsmethode für die Initialisierung im Konstruktor</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="init-in-konstruktor">Sub New()
    InitializeComponent()
    InitializeBackgroundWorker()
    InitializeProgressBar()
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="init-in-konstruktor">public Form1()
{
    InitializeComponent();
    InitializeBackgroundWorker();
    InitializeProgressBar();
}</pre>



<p><strong>In dieser Funktion bereiten wir</strong> – wie der Name schon verraten lässt – den <strong>Backgroundworker auf </strong>seine sprichwörtliche <strong>Arbeit vor</strong>.</p>



<p>Die <strong>Methode ist</strong> bewusst als <strong>Private </strong>gekennzeichnet, da ja <strong>nur die Form</strong>, bzw. <strong>dessen Konstruktor</strong> Sie <strong>verwenden </strong>soll. Von außen braucht keiner (also keine andere Klasse) darauf zugreifen.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="init-bgw-methoden">Private Sub InitializeBackgroundWorker()
    Worker = New BackgroundWorker()
    Worker.WorkerReportsProgress = True
    Worker.WorkerSupportsCancellation = True
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="init-bgw-methoden">private void InitializeBackgroundWorker()
{
    Worker = new BackgroundWorker();
    Worker.WorkerReportsProgress = true;
    Worker.WorkerSupportsCancellation = true;
}</pre>



<h4 class="wp-block-heading">Die Instanziierung</h4>



<p>Wir <strong>initialisieren </strong>die <strong>Backgroundworker</strong>-Variable mit einer <strong>neuen Instanz</strong> und <strong>konfigurieren </strong>anschließend<strong> </strong>einige <strong>Eigenschaften</strong>.</p>



<h4 class="wp-block-heading">WorkerReportsProgress</h4>



<p><strong>Wer </strong>der <strong>englischen Sprache</strong> einigermaßen <strong>mächtig</strong> ist – und das <strong>sollte man als Softwareentwickler</strong> durchaus sein – wird <strong>schnell erörtern</strong> können, was die <strong>Eigenschaft <a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.workerreportsprogress?view=net-9.0" target="_blank" rel="noreferrer noopener">WorkerReportsProgress</a></strong><a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.workerreportsprogress?view=net-9.0" target="_blank" rel="noreferrer noopener"> </a>macht.</p>



<p>Die Eigenschaft <strong>legt fest</strong>, <strong>ob </strong>der <strong>BGW Fortschrittsaktualisierungen melden kann</strong> (Standard: False).</p>



<h4 class="wp-block-heading">WorkerSupportsCancellation</h4>



<p>Auch hier lässt sich <strong>relativ einfach</strong> verstehen, was die <strong>Eigenschaft <a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.workersupportscancellation?view=net-9.0" target="_blank" rel="noreferrer noopener">WorkerSupportsCancellation</a></strong> konfigurieren soll.</p>



<p>Sie <strong>legt fest</strong>, <strong>ob </strong>der&nbsp;<strong>BackgroundWorker&nbsp;asynchrone Abbrüche unterstützt</strong> (Standard: False).</p>



<h4 class="wp-block-heading">Hilfsmethode für die ProgressBar</h4>



<p>Anbei die kleine Hilfsmethode, Welche uns bei der Vorbereitung der ProgressBar unterstützen soll.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="init-pgb">Private Sub InitializeProgressBar()
    pgbStatus.Minimum = 0
    pgbStatus.Maximum = 100
    pgbStatus.Value = 0
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="init-pgb">private void InitializeProgressBar()
{
    pgbStatus.Minimum = 0;
    pgbStatus.Maximum = 100;
    pgbStatus.Value = 0;
}</pre>



<h3 class="wp-block-heading">Den Backgroundworker starten</h3>



<figure class="wp-block-image size-full is-resized"><a href="https://robbelroot.de/wp-content/uploads/2021/09/BackgroundWorker-starten.jpg"><img decoding="async" width="640" height="360" src="https://robbelroot.de/wp-content/uploads/2021/09/BackgroundWorker-starten.jpg" alt="BackgroundWorker starten" class="wp-image-5991" style="width:640px;height:360px" title="BackgroundWorker starten"/></a><figcaption class="wp-element-caption">BackgroundWorker starten</figcaption></figure>



<p><strong>Bevor</strong> wir uns <strong>weiter </strong>mit den <strong>Details </strong>der <strong>einzelnen &#8222;Handler</strong>&#8220; beschäftigen, <strong>widmen </strong>wir uns noch dem <strong>einfacheren Szenario</strong>: Den <strong>BGW zu starten</strong>, also ihn mit seiner Arbeit loslegen zu lassen.</p>



<p>Dafür <strong>ziehen </strong>wir uns <strong>im Designer </strong>der Form einfach <strong>einen Button auf die Form </strong>und <strong>benennen Diesen </strong>natürlich passend, z. B. &#8222;btnStart&#8220;.</p>



<p><strong>Anschließend klicken </strong>wir im Designer <strong>doppelt auf </strong>den <strong>Button</strong>, um das ich nenne es mal &#8222;<strong>Standard-Ereignis</strong>&#8220; des Buttons programmieren zu können.</p>



<p><strong>Bei </strong>einem <strong>Button </strong>handelt es sich natürlich um das &#8222;<strong>Klick-Ereignis</strong>&#8222;, Welches dann mit einem passenden Ereignis-Handler (Methode) verknüpft wird. Dies geschieht durch das &#8222;Handles&#8220;-Schlüsselwort.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="btn-start-click">Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
    If Worker.IsBusy Then
        Return
    End If
    Worker.RunWorkerAsync()
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="btn-start-click">private void btnStart_Click(object sender, EventArgs e)
{
    if (Worker.IsBusy)
        return;
    Worker.RunWorkerAsync();
}</pre>



<p><strong>Im </strong>obigen <strong>Code </strong>haben wir nun <strong>eine Methode</strong> namens <strong>btnStart_Click</strong>, also ganz <strong>konform der Visual Studio Bezeichnungsregeln</strong> a la &lt;Controlname_Ereignisname&gt;.</p>



<p>Bei der <strong>Signatur des Eventhandlers</strong> handelt es sich – <strong>Aufgrund nicht nötiger Zusatzinformationen</strong> zum Klick – eher um ein &#8222;<strong>billiges Modell</strong>&#8222;.</p>



<p>Es ist <strong>lediglich der &#8222;sender&#8220;</strong> enthalten, der natürlich das Control widerspiegelt, Welches dieses Ereignis ausgelöst hat und die &#8222;<strong>Standard-Ereignisargument-Klasse</strong>&#8220; namens <strong>Eventargs</strong>.</p>



<p>Die <strong>Handles-Klausel</strong> sagt dann letztendlich aus, dass diese <strong>Sub</strong> doch bitte <strong>dann aufgerufen</strong> werden möchte, <strong>wenn </strong>der <strong>btnStart </strong>sein <strong>Klick-Ereignis signalisiert</strong>.</p>



<p><strong>So viel zur Definition</strong>, bzw. <strong>Deklaration </strong>der <strong>Handler-Methode</strong>, <strong>nun </strong>zum <strong>inneren Teil</strong>. Hier werden<strong> </strong>wir einen <strong>kleinen Check</strong> inkl. das <strong>letztendliche Starten</strong> des Backgroundworkers programmieren.</p>



<h4 class="wp-block-heading">Doppelt hält nicht immer besser</h4>



<p>Der <strong>erste Teil der Methode</strong> wird durch den folgenden <strong>kleinen Check</strong> dargestellt:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="if-busy-return">If Worker.IsBusy Then
    Return
End If</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="if-busy-return">if (Worker.IsBusy)
    return;</pre>



<p>Hier <strong>prüfen </strong>wir, <strong>ob</strong> der <strong>Backgroundworker </strong>schon <strong>beschäftigt ist</strong>, er <strong>also bereits arbeitet</strong>.</p>



<p>So wie einem der <strong>Handwerker</strong> im echten Leben <strong>vermutlich einen Vogel zeigen</strong> würde, wenn wir Ihm <strong>beim Dachdecken</strong> <strong>noch sagen</strong> würden, dass er den <strong>Rasen mähen</strong> soll, <strong>macht </strong>es <strong>auch </strong>der <strong>Backgroundworker </strong>ähnlich.</p>



<p><strong>Falls</strong> wir versuchen sollten den <strong>Backgroundworker während </strong>der <strong>Ausführung </strong>seiner Arbeit <strong>erneut zu starten</strong>, wirft er – so nennt man es &#8222;leider&#8220; – den <strong>folgenden Fehler</strong> – eine <a href="https://learn.microsoft.com/de-de/dotnet/api/system.invalidoperationexception?view=net-9.0" target="_blank" rel="noreferrer noopener">InvalidOperationException</a>:</p>



<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-invalid-operation-exception.png"><img loading="lazy" decoding="async" width="402" height="124" src="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-invalid-operation-exception.png" alt="Backgroundworker mehrfach gestartet – InvalidOperationException" class="wp-image-1926" srcset="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-invalid-operation-exception.png 402w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-invalid-operation-exception-300x93.png 300w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-invalid-operation-exception-332x102.png 332w" sizes="auto, (max-width: 402px) 100vw, 402px" /></a><figcaption class="wp-element-caption">Backgroundworker mehrfach gestartet – InvalidOperationException</figcaption></figure>



<h4 class="wp-block-heading">Der Worker als Teil vom Ganzen</h4>



<p><strong>Auch wenn</strong> es rein <strong>von </strong>der <strong>Logik </strong>her <strong>betrachtet </strong>vermutlich <strong>mehr Sinn</strong> machen würde, eine <strong>Public Property</strong> a la &#8222;<strong>Drucke Rechnungen</strong>&#8220; vom <strong>Typ Boolean</strong> hinzuzufügen, <strong>prüfen </strong>wir die <strong>Ausführung </strong>des <strong>Backgroundworkers </strong>in diesem simplen Beispiel <strong>direkt</strong>.</p>



<p>Die <strong>öffentliche Eigenschaft</strong> wäre meiner Meinung nach hier <strong>deshalb eher angebracht</strong>, <strong>weil der Status</strong> des Backgroundworkers ja <strong>nicht der ausschlaggebende Punkt</strong> für eine größere Aufgabe darstellt. Sie stellt <strong>eher einen kleinen Teil des Großen und Ganzen</strong> dar.</p>



<p>Wenn wir <strong>zum Beispiel die Aufgabe</strong> hätten die <strong>gesammelten Rechnungen</strong> der letzten Tage <strong>zu drucken</strong>, dann machen wir <strong>die Ausführung des Backgroundworkers</strong> – Welcher ja zum Beispiel <strong>nur das Sammeln und Aufarbeiten der Rechnungen übernehmen</strong> könnte – eher <strong>vom übergeordneten Flag</strong> namens (z. B.) <strong>IsPrintingBills </strong>abhängig.</p>



<h4 class="wp-block-heading">Ein Bild zur Veranschaulichung</h4>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-vertically-aligned-top is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-large is-resized"><a href="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-Beispiel-mit-Sub-Prozessen.png"><img loading="lazy" decoding="async" width="375" height="424" src="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-Beispiel-mit-Sub-Prozessen.png" alt="Backgroundworker Beispiel mit Sub-Prozessen bzw. Methoden" class="wp-image-1931" style="width:265px;height:299px" srcset="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-Beispiel-mit-Sub-Prozessen.png 375w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-Beispiel-mit-Sub-Prozessen-265x300.png 265w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-Beispiel-mit-Sub-Prozessen-332x375.png 332w" sizes="auto, (max-width: 375px) 100vw, 375px" /></a><figcaption class="wp-element-caption">Backgroundworker Beispiel mit Sub-Prozessen bzw. Methoden</figcaption></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p><strong>Die Aufbereitung</strong> der Rechnungen, <strong>also </strong>der <strong>Arbeitsabschnitt vom BGW</strong>, ist ja letztendlich nur <strong>ein kleiner Teil</strong> davon. Es <strong>könnten ja</strong> zum Beispiel <strong>vorher und nachher noch Datenbankzugriffe uvm. stattfinden</strong>.</p>



<p>Im Bild stellt der <strong>BGW </strong>praktisch <strong>nur </strong>den <strong>Sub-Prozess</strong> bzw. <strong>Methode 3</strong> des <strong>Gesamten </strong>dar.</p>



<p>Jeweilige <strong>andere Methoden</strong> könnten daher natürlich auch wiederum <strong>eigene</strong>, spezielle <strong>Exceptions </strong>– also Fehler – &#8222;werfen&#8220; und somit <strong>separat abgefangen </strong>und <strong>verarbeitet </strong>werden.</p>
</div>
</div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h4 class="wp-block-heading">Der Start selbst</h4>



<p>Den <strong>Backgroundworker</strong> final <strong>starten</strong>, können wir <strong>mit </strong>dessen <strong>Methode namens <a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.runworkerasync?view=net-9.0" target="_blank" rel="noreferrer noopener">RunWorkerAsync</a></strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="run-worker-async">Worker.RunWorkerAsync()</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="run-worker-async">Worker.RunWorkerAsync();</pre>



<h3 class="wp-block-heading">Mit dem Backgroundworker arbeiten</h3>



<p><strong>Nachdem </strong>wir nun die <strong>allgemeinen Vorbereitungen</strong> getroffen haben und <strong>Nebeninformationen besprochen</strong> haben, kommen wir nun <strong>final zu den restlichen Aspekten</strong>.</p>



<h4 class="wp-block-heading">Der DoWork Handler</h4>



<p><strong>Als erstes</strong> brauchen wir <strong>eine Methode</strong>, die ausgeführt wird, <strong>wenn </strong>der <strong>Worker </strong>sein &#8222;<strong>DoWork-Ereignis</strong>&#8220; signalisiert. <strong>Dort </strong>programmieren wir das <strong>hinein</strong>, <strong>was </strong>letztendlich <strong>im Hintergrund </strong>– also <strong>asynchron </strong>– <strong>ausgeführt </strong>wird.</p>



<p>Die grobe <strong>Signatur </strong>inkl. <strong>Handler-Verknüpfung</strong> und <strong>leerer Sub</strong> sieht so aus:</p>
</div></div>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bgw-do-work">Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
    ' what to do?
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bgw-do-work">// bei C# die Verknüpfung von Ereignis zu Handler nicht vergessen!
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    // what to do?
}</pre>



<p>Die <strong>erste Frage</strong> die man sich <strong>nun </strong>stellen könnte wäre: &#8222;Okay, und <strong>wie übergebe ich dem Backgroundworker</strong> jetzt <strong>einen Parameter</strong>?&#8220;</p>



<h4 class="wp-block-heading">Backgroundworker einen Parameter übergeben</h4>



<p>Das ist natürlich etwas, <strong>was sich jeder Anfänger</strong> in der Verwendung des BGWs einmal <strong>fragen wird</strong> und <strong>im Endeffekt</strong> ist es – wenn man weiß, wo man suchen muss – gar <strong>nicht so schwer</strong>.</p>



<p><strong>Wer sich</strong> die <strong>Methode</strong> <strong><a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.runworkerasync?view=net-9.0" target="_blank" rel="noreferrer noopener">RunWorkerAsync</a></strong> einmal <strong>genauer angeschaut</strong> hat, wird feststellen, dass man <strong>in einer weiteren Überladung</strong> der Methode <strong>auch etwas als Parameter mitgeben</strong> kann.</p>



<p>Würden wir analog zu unserem Beispiel <strong>nur die Rechnungen von heute</strong> abarbeiten wollen, <strong>könnte man</strong> es zum Beispiel <strong>so lösen</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bgw-ein-parameter">Worker.RunWorkerAsync("today")</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bgw-ein-parameter">Worker.RunWorkerAsync("today");</pre>



<p>In dem <strong>DoWork-Handler</strong> können wir dann <strong>via e.Argument an den übergebenen Parameter</strong> kommen. Da es sich bei dem Argument um ein <strong>Object </strong>handelt, müssen wir es noch <strong>in den korrekten Datentyp casten</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="einen-parameter-parsen">Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
    Dim argument = Convert.ToString(e.Argument)
    ' do something with the passed argument
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="einen-parameter-parsen">private void Worker_DoWork(object sender, DoWorkEventArgs e)
{ 
   var argument = Convert.ToString(e.Argument);
   // do something with the passed argument
}</pre>



<h4 class="wp-block-heading">Backgroundworker mehrere Parameter übergeben</h4>



<p>Nun könnte man sich <strong>als nächstes die Frage</strong> stellen: &#8222;Okay und was mache ich nun, wenn ich dem <strong>Backgroundworker mehrere Parameter</strong> übergeben möchte? So geht es ja <strong>nur mit einem Parameter</strong>!&#8220;</p>



<p><strong>Wie sagt man so schön oft und gerne</strong> in der Programmierung: &#8222;<strong>It depends</strong>&#8220; – &#8222;<strong>Es kommt darauf an</strong>&#8222;. Es <strong>gibt sicherlich</strong> gewisse <strong>Fallbeispiele</strong>, <strong>in denen es reichen würde</strong> z. B. eine <strong>ein Datum</strong> und eine <strong>Kunden-ID</strong> wie folgt zu übergeben:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bgw-mehrere-parameter-schlampi">Worker.RunWorkerAsync("today,5")</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bgw-mehrere-parameter-schlampi">Worker.RunWorkerAsync("today,5");</pre>



<p>So könnte man <strong>diese Parameter </strong>dann einfach <strong>in </strong>dem <strong>DoWork-Handler abgreifen</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bgw-mehrere-params-parsen">Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
    Dim arguments = Convert.ToString(e.Argument).Split(",")
    Dim date = arguments(0)
    Dim customerId = Convert.ToInt32(arguments(1))
    ' do something
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bgw-mehrere-params-parsen">private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    var arguments = Convert.ToString(e.Argument).Split(",");
    var date = arguments(0);
    var customerId = Convert.ToInt32(arguments(1));
    // do something
}</pre>



<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/06/stop.jpg"><img loading="lazy" decoding="async" width="1024" height="576" src="https://robbelroot.de/wp-content/uploads/2021/06/stop-1024x576.jpg" alt="Stop den BGW so besser nicht verwenden!" class="wp-image-1947" srcset="https://robbelroot.de/wp-content/uploads/2021/06/stop-1024x576.jpg 1024w, https://robbelroot.de/wp-content/uploads/2021/06/stop-300x169.jpg 300w, https://robbelroot.de/wp-content/uploads/2021/06/stop-768x432.jpg 768w, https://robbelroot.de/wp-content/uploads/2021/06/stop-700x393.jpg 700w, https://robbelroot.de/wp-content/uploads/2021/06/stop-332x187.jpg 332w, https://robbelroot.de/wp-content/uploads/2021/06/stop.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Stop den Backgroundworker so besser nicht verwenden!</figcaption></figure>



<p><strong>Allerdings </strong>ist <strong>diese Methode</strong> <strong>weder sauber</strong>, <strong>noch </strong>sehr <strong>zukunftssicher</strong>, <strong>ändert sich mal was</strong> an der Schreibweise, <strong>kommen neue Werte dazu</strong>, oder <strong>ändert sich die Reihenfolge</strong>, könnte man schon wieder ein Problem haben.</p>



<p><strong>Auch wenn</strong> ein <strong>anderer Programmierer</strong>, der zum Beispiel in der gleichen Firma wie Ihr arbeitet, <strong>den Code falsch aufruft</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="falsche-param-reihenfolge">Worker.RunWorkerAsync("5,today")</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="falsche-param-reihenfolge">Worker.RunWorkerAsync("5,today");</pre>



<p><strong>sprich </strong>die <strong>Reihenfolge vertauscht</strong>, oder das <strong>falsche Trennzeichen</strong> verwendet, gibt es <strong>direkt wieder Probleme</strong>.</p>



<h4 class="wp-block-heading">Richtig mehrere Parameter übergeben</h4>



<p><strong>Wie man</strong> es <strong>stattdessen </strong>&#8222;<strong>richtig</strong>&#8220; machen könnte sieht man <strong>in folgendem Beispiel</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bill-print-args">Public Class BillPrintArgs

    Public [Date] As String
    Public CustomerId As Integer

    Sub New([date] As String, customerId As Integer)
        Me.Date = [date]
        Me.CustomerId = customerId
    End Sub

End Class</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bill-print-args">public class BillPrintArgs
{

    public string Date { get; set; }
    public int CustomerId { get; set; }

    public BillPrintArgss(string date, int customerId)
    {
        Date = date;
        CustomerId = customerId;
    }

}</pre>



<p>Ich habe hier eine <strong>extra dafür gebaute Klasse</strong> erstellt, die <strong>die jeweiligen Parameter</strong> dann <strong>als Properties/Eigenschaften</strong> anbietet. Der <strong>Konstruktor der Klasse</strong> bietet mir auch sofort <strong>die Möglichkeit passende Werte mitzuliefern</strong>.</p>



<p>Da ich <strong>nicht von der bisherigen Bezeichnung abweichen</strong> wollte, habe ich nun e<strong>inen kleinen Workaround</strong> – die eckigen Klammern – nutzen müssen. &#8222;<strong>Date</strong>&#8220; wird ansonsten als<strong> reservierter Begriff erkannt</strong> und kann nicht verwendet werden.</p>



<p>Nun könnte der Aufruf der <strong>RunWorkerAsync</strong>-Methode <strong>wie folgt</strong> aussehen:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bill-print-args-aufruf">Dim billPrintArgs = New BillPrintArgs("today", 5)
Worker.RunWorkerAsync(billPrintArgs)</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bill-print-args-aufruf">var billPrintArgs = new BillPrintArgs("today", 5);
Worker.RunWorkerAsync(billPrintArgs);</pre>



<p><strong>In diesem Fall</strong> würde man dann <strong>so typensicher</strong> <strong>an </strong>das jeweilige <strong>Argument kommen</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bill-print-args-dowork">Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
    Dim billPrintArgs = CType(e.Argument, BillPrintArgs)
    ' do something with the passed argument
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bill-print-args-dowork">private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    var billPrintArgs = (BillPrintArgs) e.Argument;
    // do something with the passed argument
}</pre>



<h3 class="wp-block-heading">Achtung beim Zugriff auf die GUI</h3>



<p><strong>Da </strong>der <strong>Backgroundworker im Hintergrund arbeitet</strong>, sprich <strong>in</strong> einem <strong>anderen Thread</strong>, kann man <strong>nicht wie gewohnt auf </strong>die <strong>GUI zugreifen</strong>.</p>



<h4 class="wp-block-heading">Threadübergreifender Vorgang</h4>



<p><strong>Versucht </strong>man dies z.B. <strong>wie folgt</strong> dennoch:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bgw-dowork-ui-zugriff">Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
    lblStatus.Text = "Test"
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bgw-dowork-ui-zugriff">private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    lblStatus.Text = "Test";
}</pre>



<p><strong>bekommt </strong>man einen <strong>Fehler</strong>:</p>



<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/06/backgroundworker-exception-thread-uebergreifener-vorgang.png"><img loading="lazy" decoding="async" width="399" height="138" src="https://robbelroot.de/wp-content/uploads/2021/06/backgroundworker-exception-thread-uebergreifener-vorgang.png" alt="InvalidOperationException – Threadübergreifender Vorgang" class="wp-image-1987" srcset="https://robbelroot.de/wp-content/uploads/2021/06/backgroundworker-exception-thread-uebergreifener-vorgang.png 399w, https://robbelroot.de/wp-content/uploads/2021/06/backgroundworker-exception-thread-uebergreifener-vorgang-300x104.png 300w, https://robbelroot.de/wp-content/uploads/2021/06/backgroundworker-exception-thread-uebergreifener-vorgang-332x115.png 332w" sizes="auto, (max-width: 399px) 100vw, 399px" /></a><figcaption class="wp-element-caption">Backgroundworker InvalidOperationException – Threadübergreifender Vorgang</figcaption></figure>



<h3 class="wp-block-heading">Backgroundworker abbrechen / canceln</h3>



<p><strong>Hat </strong>der <strong>Backgroundworker erstmal </strong>seine Arbeit <strong>begonnen</strong>, <strong>können wir</strong> Diesem auch <strong>ein Abbruchsignal</strong> senden, <strong>falls </strong>der <strong>Benutzer </strong>unserer Anwendung <strong>zum Beispiel das Programm schließt</strong>.</p>



<p><strong>Eventuell </strong>entscheidet sich der <strong>Anwender </strong>auch <strong>aus anderen Gründen </strong>dazu <strong>den Prozess </strong>– zum Beispiel durch einen Button –<strong> abzubrechen</strong>.</p>



<h4 class="wp-block-heading">Achtung &#8211; Fehler</h4>



<p><strong>Voraussetzung </strong>für das <strong>Abbruchsignal </strong>an den Backgroundworker <strong>ist</strong>, die <strong>jeweilige Eigenschaft</strong> dafür vorher korrekt konfiguriert zu haben, sprich <a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.workersupportscancellation?view=net-9.0" target="_blank" rel="noreferrer noopener"><strong>WorkerSupportsCancellation</strong></a>, <strong>ansonsten funktioniert</strong> das Ganze <strong>nicht</strong>.</p>



<p><strong>Senden wir</strong> dem Backgroundworker über die Methode <strong><a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.cancelasync?view=net-9.0" target="_blank" rel="noreferrer noopener">CancelAsync</a> trotzdem ein Abbruchsignal</strong> und haben dabei vergessen, die <a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.workersupportscancellation?view=net-9.0" target="_blank" rel="noreferrer noopener"><strong>WorkerSupportsCancellation </strong></a>Eigenschaft auf &#8222;True&#8220; zu setzen, <strong>kommt folgender Fehler</strong>:</p>



<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-abbruch.png"><img loading="lazy" decoding="async" width="401" height="140" src="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-abbruch.png" alt="Backgroundworker InvalidOperationException – Abbruch wird nicht unterstützt" class="wp-image-1965" srcset="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-abbruch.png 401w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-abbruch-300x105.png 300w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-abbruch-332x116.png 332w" sizes="auto, (max-width: 401px) 100vw, 401px" /></a><figcaption class="wp-element-caption">Backgroundworker InvalidOperationException – Abbruch wird nicht unterstützt</figcaption></figure>



<h4 class="wp-block-heading">Der Abbruch</h4>



<p><strong>Wir </strong>fügen als nächstes einen <strong>neuen Button und</strong> einen <strong>Handler </strong>hinzu:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="btn-cancel-click">Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
    Worker.CancelAsync()
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="btn-cancel-click">private void btnCancel_Click(object sender, EventArgs e)
{
    Worker.CancelAsync();
}</pre>



<p>Der <strong>Button ruft</strong> dann die <strong>CancelAsync</strong>-Methode auf. <strong>Zunächst bewirkt dies nichts!</strong> Denn wir <strong>müssen darauf</strong> explizit in dem DoWork-Handler <strong>reagieren</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="dowork-mit-cancel">Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
    Dim billPrintArgs = CType(e.Argument, BillPrintArgs)
    For i = 0 To 1000000
        If Worker.CancellationPending Then
            e.Cancel = True
            Return
        End If
        ' Do something..
        Thread.Sleep(200)
    Next
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="dowork-mit-cancel">private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    var billPrintArgs = (BillPrintArgs) e.Argument;
    for (var i = 0; i &lt;= 1000000; i++)
    {
        if (Worker.CancellationPending)
        {
            e.Cancel = true;
            Return;
        }
        // Do something..
        Thread.Sleep(200);
    }
}</pre>



<h4 class="wp-block-heading">Auf CancellationPending achten</h4>



<p><strong>Wenn </strong>der <strong>Backgroundworker </strong>nun ein <strong>Abbruchsignal </strong>bekommen hat, würde <strong>die Eigenschaft <a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.cancellationpending?view=net-9.0" target="_blank" rel="noreferrer noopener">CancellationPending</a></strong> auf <strong>True </strong>stehen und <strong>dadurch </strong>das <strong>e.Cancel Flag auf True gesetzt</strong> werden.</p>



<p><strong>Anschließend </strong>wird die Methode <strong>noch mit Return verlassen</strong> und die <strong>For-Schleife</strong> somit <strong>abgebrochen</strong>/<strong>beendet</strong>.</p>



<h4 class="wp-block-heading">Auf Abbruch reagieren</h4>



<p>Im <strong><a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.runworkercompleted?view=net-9.0" target="_blank" rel="noreferrer noopener">RunWorkerCompleted</a></strong>-Handler kann man mit Hilfe der <strong><a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.runworkercompletedeventargs?view=net-9.0" target="_blank" rel="noreferrer noopener">RunWorkerCompletedEventArgs</a></strong> überprüfen, <strong>ob </strong>es sich um einen <strong>Abbruch </strong>handelt.</p>



<p><strong>Dazu </strong>schaut man sich den <strong>Wert in der EventArgs</strong>&#8211;<strong>Eigenschaft </strong>namens <strong>Cancelled </strong>an (e.Cancelled).</p>



<h3 class="wp-block-heading">Backgroundworker Statusmeldungen</h3>



<p><strong>Damit </strong>der <strong>Backgroundworker Statusmeldungen </strong>von sich geben kann, <strong>müssen </strong>wir Ihn mit der <strong>Eigenschaft <a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.workerreportsprogress?view=net-9.0" target="_blank" rel="noreferrer noopener">WorkerReportsProgress</a></strong> auf True konfigurieren.</p>



<h4 class="wp-block-heading">Achtung Fehler</h4>



<p><strong>Falls wir</strong> – wie oben beim Abbruch – auch hier <strong>vergessen sollten</strong>, die <strong>Eigenschaft </strong>auf <strong>True </strong>zu stellen, werden wir auch hier <strong>mit einem Fehler abgespeist</strong>:</p>



<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-report-progress.png"><img loading="lazy" decoding="async" width="399" height="138" src="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-report-progress.png" alt="Backgroundworker InvalidOperationException – Statusmeldungen werden nicht unterstützt" class="wp-image-1974" srcset="https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-report-progress.png 399w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-report-progress-300x104.png 300w, https://robbelroot.de/wp-content/uploads/2021/06/Backgroundworker-kein-support-fuer-report-progress-332x115.png 332w" sizes="auto, (max-width: 399px) 100vw, 399px" /></a><figcaption class="wp-element-caption">Backgroundworker InvalidOperationException – Statusmeldungen werden nicht unterstützt</figcaption></figure>



<p>Ist alles <strong>korrekt konfiguriert</strong>, <strong>können </strong>wir nun <strong>in </strong>dem <strong>DoWork-Handler</strong> die <strong><a href="https://learn.microsoft.com/de-de/dotnet/api/system.componentmodel.backgroundworker.reportprogress?view=net-9.0" target="_blank" rel="noreferrer noopener">ReportProgress</a></strong>-Methode des Backgroundworkers <strong>verwenden</strong>.</p>



<h4 class="wp-block-heading">Statusmeldungen abgeben</h4>



<p>Dabei können wir auf <strong>2 Varianten</strong> zurückgreifen:</p>



<ul class="wp-block-list">
<li>ReportProgress(&lt;FortschrittInProzent&gt;)</li>



<li>ReportProgress(&lt;FortschrittInProzent&gt;, &lt;EigenesObjekt&gt;)</li>
</ul>



<p><strong>Wenn man</strong> also stumpf den <strong>Prozentwert weiterleiten </strong>möchte, <strong>reicht </strong>wohl die <strong>erste Überladung</strong> der Methode aus.</p>



<p><strong>Möchte man</strong> jedoch <strong>komplexere Daten weitergeben</strong>, <strong>empfiehlt </strong>es sich auch hier, <strong>eine eigene Klasse</strong> zu schreiben</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bill-print-progress-args">Public Class BillPrintProgressArgs

    Public Property Information As String

    ' more Properties..

    Sub New(information As String)
        Me.Information = information
    End Sub

End Class</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bill-print-progress-args">public class BillPrintProgressArgs
{

    public string Information { get; set; }

    // more Properties..

    public BillPrintProgressArgs(string information)
    {
        Information = information;
    }

}</pre>



<p>und die <strong>zweite Überladung</strong> zu verwenden:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bgw-dowork-zweit-overload">Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
    Dim billPrintArgs = CType(e.Argument, BillPrintArgs)
    ' do something with args
    Dim maxIterations = 1000
    For i = 0 To maxIterations
        If Worker.CancellationPending Then
            e.Cancel = True
            Return
        End If
        Thread.Sleep(20)
        Dim percentage = Convert.ToInt32((i / maxIterations) * 100)
        Worker.ReportProgress(percentage , new BillPrintProgressArgs("My information: " &amp; i))
    Next
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bgw-dowork-zweit-overload">private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    var billPrintArgs = (BillPrintArgs) e.Argument;
    // do something with args
    var maxIterations = 1000;
    for (var i = 0; i &lt;= maxIterations; i++)
    {
        if (Worker.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
        Thread.Sleep(20);
        var percentage = Convert.ToInt32((i / maxIterations) * 100);
        Worker.ReportProgress(percentage , new BillPrintProgressArgs("My information: " + i));
    }
}</pre>



<h4 class="wp-block-heading">Statusmeldungen empfangen und verarbeiten</h4>



<p><strong>Nun </strong>können wir <strong>in dem</strong> dafür vorgesehenen <strong>Handler </strong>die<strong> jeweiligen Informationen verarbeiten</strong>. Wir können <strong>den Text</strong> mit der Information über die <strong>i-Variable</strong> <strong>aktualisieren</strong>. <strong>Ebenfalls </strong>können wir die <strong>Progressbar aktualisieren</strong>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="bgw-progress-handler">Private Sub Worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Worker.ProgressChanged
    Dim billPrintProgressArgs = CType(e.UserState, BillPrintProgressArgs)
    lblStatus.Text = "Status: " &amp; billPrintProgressArgs.Information
    pgbStatus.Value = e.ProgressPercentage
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="bgw-progress-handler">private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    var billPrintProgressArgs = (BillPrintProgressArgs) e.UserState;
    lblStatus.Text = "Status: " + billPrintProgressArgs.Information;
    pgbStatus.Value = e.ProgressPercentage;
}</pre>



<h2 class="wp-block-heading"><strong>Moderne Alternativen zum BackgroundWorker (.NET 6+)</strong></h2>



<p>Der BackgroundWorker hat – sofern du nicht an eine ältere .NET Framework-Version gebunden bist – aus meiner Sicht mehr als ausgedient. Das event-basierte Modell mit DoWork, ProgressChanged und RunWorkerCompleted ist umständlich und fehleranfällig. Seit .NET 4.5 gibt es mit <code>async/await</code> und <code>Task.Run</code> eine elegantere Lösung.</p>



<p>Hier ein Überblick:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Technologie</th><th>Ab Version</th><th>Vorteil</th></tr></thead><tbody><tr><td>Async/Await + Task.Run</td><td>.NET 4.5+</td><td>Einfacher Code, kein Event-Wiring</td></tr><tr><td>IProgress</td><td>.NET 4.5+</td><td>Typsichere Fortschrittsmeldungen</td></tr><tr><td>Channels</td><td>.NET Core 3.0+</td><td>Producer/Consumer Szenarien</td></tr><tr><td>PeriodicTimer</td><td>.NET 6+</td><td>Interval-basierte Hintergrundarbeit</td></tr></tbody></table></figure>



<p>Um den Unterschied konkret zu zeigen, hier die gleiche Aufgabe einmal mit dem BackgroundWorker und einmal mit dem modernen <code>async/await</code>-Pattern:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="modern-async-await-pattern">Private Async Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
    Dim progress = New Progress(Of Integer)(Sub(p) pgbStatus.Value = p)
    Await Task.Run(Sub()
        For i = 0 To 100
            Thread.Sleep(20) ' Simulierte Arbeit
            CType(progress, IProgress(Of Integer)).Report(i)
        Next
    End Sub)
    lblStatus.Text = "Fertig!"
End Sub</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="modern-async-await-pattern">private async void btnStart_Click(object sender, EventArgs e)
{
    var progress = new Progress&lt;int>(p => pgbStatus.Value = p);
    await Task.Run(() =>
    {
        for (int i = 0; i &lt;= 100; i++)
        {
            Thread.Sleep(20); // Simulierte Arbeit
            ((IProgress&lt;int>)progress).Report(i);
        }
    });
    lblStatus.Text = "Fertig!";
}</pre>



<p>Kein <code>DoWork</code>-Handler, kein <code>ProgressChanged</code>-Event, kein <code>RunWorkerCompleted</code>. Der gesamte Ablauf steckt in einer einzigen Methode – wesentlich lesbarer. Darüber kannst Du in meinem passenden Beitrag über <a href="https://robbelroot.de/blog/vbnet-await/" type="post" id="3746"><strong>VB NET Async Await</strong></a> mehr erfahren.</p>



<p>Neue Projekte sollten grundsätzlich auf dieses Pattern setzen. Den BackgroundWorker brauchst du nur noch, wenn du explizit auf .NET Framework 4.0 oder älter abzielen musst.</p>



<!-- CTA Block -->
<div style="position:relative;background:#1a1a2e;border-radius:12px;padding:36px 32px;margin:40px 0;overflow:hidden;color:#fff;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif">
  <div style="position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.03) 1px,transparent 1px);background-size:20px 20px;pointer-events:none"></div>
  <div style="position:absolute;top:-40px;right:-40px;width:200px;height:200px;background:radial-gradient(circle,rgba(230,126,34,.18),transparent 70%);pointer-events:none"></div>
  <div style="position:relative">
    <span style="display:inline-block;background:rgba(230,126,34,.15);color:#e67e22;font-size:11px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;padding:4px 10px;border-radius:6px;margin-bottom:14px">VB.NET &amp; C# Hilfe</span>
    <p style="font-size:22px;font-weight:800;margin:0 0 10px;line-height:1.3">BackgroundWorker, Async/Await &#038; Co. – kein Durchblick?</p>
    <p style="color:#aab4c8;font-size:15px;margin:0 0 22px;max-width:560px">Multithreading muss kein Albtraum sein. In meinem 1:1 Unterricht erkläre ich dir alles verständlich – vom BGW bis zu modernen Async-Patterns.</p>
    <div style="display:flex;flex-wrap:wrap;gap:10px">
      <a href="https://robbelroot.de/kontakt/" style="display:inline-block;background:#e67e22;color:#fff;font-weight:700;font-size:14px;padding:12px 24px;border-radius:8px;text-decoration:none">Jetzt Kontakt aufnehmen</a>
      <a href="https://robbelroot.de/portfolio/" style="display:inline-block;background:transparent;color:#fff;font-weight:600;font-size:14px;padding:12px 24px;border-radius:8px;text-decoration:none;border:1px solid rgba(255,255,255,.2)">Über mich</a>
    </div>
  </div>
</div>



<h2 class="wp-block-heading">FAQ</h2>



<div class="schema-faq wp-block-yoast-faq-block"><div class="schema-faq-section" id="faq-question-1774435644578"><strong class="schema-faq-question">Wie übergebe ich dem BackgroundWorker mehrere Parameter?</strong> <p class="schema-faq-answer">Erstelle eine eigene Klasse mit den gewünschten Eigenschaften und übergib eine Instanz davon an &lt;code>RunWorkerAsync()&lt;/code>. Im &lt;code>DoWork&lt;/code>-Handler castest du &lt;code>e.Argument&lt;/code> zurück in deinen Typ. Das ist typsicher und zukunftsfest – im Gegensatz zu String-Splitting.</p> </div> <div class="schema-faq-section" id="faq-question-1774435754920"><strong class="schema-faq-question">Ist der BackgroundWorker noch zeitgemäß?</strong> <p class="schema-faq-answer">Für neue Projekte ab .NET 4.5+ empfiehlt sich <code>async/await</code> mit <code>Task.Run</code> und <code>IProgress&lt;T></code>. Der BackgroundWorker funktioniert weiterhin, ist aber durch das Event-basierte Modell umständlicher als moderne Alternativen.</p> </div> <div class="schema-faq-section" id="faq-question-1774435780737"><strong class="schema-faq-question">Warum bekomme ich „Ungültiger threadübergreifender Vorgang&#8220; beim BackgroundWorker?</strong> <p class="schema-faq-answer">Der <code>DoWork</code>-Handler läuft in einem separaten Thread. Direkter Zugriff auf GUI-Elemente (Labels, ProgressBar etc.) ist dort nicht erlaubt. Nutze stattdessen <code>ReportProgress()</code> und reagiere im <code>ProgressChanged</code>-Handler – dieser läuft im UI-Thread.</p> </div> </div>



<h2 class="wp-block-heading">Der vollständige Code</h2>



<p><strong>Wer </strong>es <strong>eilig </strong>hat, <strong>kann </strong>sich den vollständigen Code direkt <strong>hier herauskopieren</strong>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="vollstaendiger-code">Imports System.ComponentModel
Imports System.Threading

Public Class Form1

    Private WithEvents Worker As BackgroundWorker

    Sub New()
        InitializeComponent()
        InitializeBackgroundWorker()
        InitializeProgressBar()
    End Sub

    Private Sub InitializeBackgroundWorker()
        Worker = New BackgroundWorker()
        Worker.WorkerReportsProgress = True
        Worker.WorkerSupportsCancellation = True
    End Sub

    Private Sub InitializeProgressBar()
        pgbStatus.Minimum = 0
        pgbStatus.Maximum = 100
        pgbStatus.Value = 0
    End Sub

    Public Class BillPrintArgs

        Public [Date] As String

        Public CustomerId As Integer

        Sub New([date] As String, customerId As Integer)
            Me.Date = [date]
            Me.CustomerId = customerId
        End Sub

    End Class

    Public Class BillPrintProgressArgs

        Public Property Information As String

        ' more Properties..

        Sub New(information As String)
            Me.Information = information
        End Sub

    End Class

    Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
        Dim billPrintArgs = CType(e.Argument, BillPrintArgs)
        ' do something with args
        Dim maxIterations = 1000
        For i = 1 To maxIterations
            If Worker.CancellationPending Then
                e.Cancel = True
                Return
            End If
            Thread.Sleep(20)
            Dim percentage = Convert.ToInt32((i / maxIterations) * 100)
            Worker.ReportProgress(percentage, New BillPrintProgressArgs("Information: " &amp; i.ToString()))
        Next
    End Sub

    Private Sub Worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Worker.ProgressChanged
        Dim billPrintProgressArgs = CType(e.UserState, BillPrintProgressArgs)
        lblStatus.Text = "Status: " &amp; billPrintProgressArgs.Information
        pgbStatus.Value = e.ProgressPercentage
    End Sub

    Private Sub Worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles Worker.RunWorkerCompleted
        lblStatus.Text = "Worker completed – Cancelled: " &amp; e.Cancelled.ToString()
    End Sub

    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        If Worker.IsBusy Then
            Return
        End If
        Dim billPrintArgs = New BillPrintArgs(DateTime.Now.ToString("dd.MM.YYYY"), 5)
        lblStatus.Text = "Gestartet"
        pgbStatus.Value = 0
        Worker.RunWorkerAsync(billPrintArgs)
    End Sub

    Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
        Worker.CancelAsync()
    End Sub

End Class</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="vollstaendiger-code">using System.ComponentModel;
using System.Threading;

public class Form1
{

    private BackgroundWorker Worker;

    public Form1()
    {
        InitializeComponent();
        InitializeBackgroundWorker();
        InitializeProgressBar();
    }

    private void InitializeBackgroundWorker()
    {
        Worker = new BackgroundWorker();
        Worker.WorkerReportsProgress = true;
        Worker.WorkerSupportsCancellation = true;
    }

    private void InitializeProgressBar()
    {
        pgbStatus.Minimum = 0;
        pgbStatus.Maximum = 100;
        pgbStatus.Value = 0;
    }

    public class BillPrintArgs
    {

        public string Date { get; set; }

        public int CustomerId { get; set; }

        public BillPrintArgs(string date, int customerId)
        {
            Date = date;
            CustomerId = customerId;
        }

    }

    public class BillPrintProgressArgs
    {

        public string Information { get; set; }

        // more Properties..

        public BillPrintProgressArgs(string information)
        {
            Information = information;
        }

    }

    private void Worker_DoWork(object sender, DoWorkEventArgs e)
        var billPrintArgs = (BillPrintArgs) e.Argument;
        // do something with args
        var maxIterations = 1000;
        for (var i = 1; i &lt;= maxIterations; i++)
            if (Worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            Thread.Sleep(20);
            var percentage = Convert.ToInt32((i / maxIterations) * 100);
            Worker.ReportProgress(percentage, New BillPrintProgressArgs("Information: " + i.ToString()));
        }
    }

    private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {    
        var billPrintProgressArgs = (BillPrintProgressArgs) e.UserState;
        lblStatus.Text = "Status: " + billPrintProgressArgs.Information;
        pgbStatus.Value = e.ProgressPercentage;
    }

    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        lblStatus.Text = "Worker completed – Cancelled: " + e.Cancelled.ToString();
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        if (Worker.IsBusy)
            return;
        var billPrintArgs = new BillPrintArgs(DateTime.Now.ToString("dd.MM.YYYY"), 5);
        lblStatus.Text = "Gestartet";
        pgbStatus.Value = 0;
        Worker.RunWorkerAsync(billPrintArgs);
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        Worker.CancelAsync();
    }

}</pre>



<h2 class="wp-block-heading">Downloads</h2>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="https://robbelroot.de/datei-download/?dlid=9f4f053c-2af6-c447-d6fa-c61ede3054e3&amp;utm_source=robbelroot_hp&amp;utm_medium=blog_post&amp;utm_campaign=general" target="_blank" rel="noreferrer noopener">BgwExample.zip</a></div>
</div>
<p>Der Beitrag <a href="https://robbelroot.de/blog/backgroundworker-beispiel-in-vb-net/">Die ultimative VB.NET Background Worker Anleitung in 2026</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://robbelroot.de/blog/backgroundworker-beispiel-in-vb-net/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
	</channel>
</rss>
