Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
"Die angeforderte Ressource wird bereits verwendet"
MoaByter
myCSharp.de - Member



Dabei seit:
Beiträge: 62
Herkunft: Berlin

Themenstarter:

"Die angeforderte Ressource wird bereits verwendet"

beantworten | zitieren | melden

hai und hallo,

ich bekam beim Debuggen die im Titel genannte Meldung und wüsste jetzt gerne, ob ich mit meiner Vermutung richtig liege.

Bei der zweiten Zeile (wbInfo = WebBrowser) kam die Meldung:

string txt1 = "Aktualisierung in: " + min + ":" + s_sec + i_sec + " min";
wbInfo.DocumentText = doc.Replace(m_rplc.Groups[1].Value, txt1);
return;

Auf den WebBrowser wird in gleicher Form von mehreren Stellen aus zugegriffen, allerdings sollte das vom Ablauf her nie gleichzeitig/überschneidend passieren - eigentlich auch beim Debuggen nicht. Wie frage ich ab, ob das WebBrowser.Dokument gerade beschrieben wird? Ich finde dazu leider nichts.

Der Fehler scheint auch nicht oft aufzutreten, er ließ sich jedenfalls nicht reproduzieren.
Danke für Hilfe/Kommentare.

...lypô
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.758
Herkunft: Düsseldorf

beantworten | zitieren | melden

Ohne mich wirklich mit diesem Control auszukennen:

Kommen die Zugriffe aus verschiedenen Threads? Es klingt ein wenig danach, da Du von gleichzeitigen Zugriffen (bzw. deren Ausbleiben) schreibst.
Es ist egal, ob die Zugriffe gleichzeitig passieren oder nicht, verschiedene Threads sind nicht erlaubt.
Ehrlich gesagt würde ich da aber eine bessere Fehlermeldung erwarten ...

Du kannst es ja mal in einem kleinen Test-Projekt nachstellen
private Nachricht | Beiträge des Benutzers
MoaByter
myCSharp.de - Member



Dabei seit:
Beiträge: 62
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Danke für deine Antwort.

Ja, es sind mehrere Threads. Mittlerweile ist die Meldung aber wieder aufgetaucht: Während des Debuggens beim RechtsMausKlick auf den Browser während ein Timer die Zeitangabe alle Sekunden verändert. Ob das nun nur während des Debuggens auftritt, weiß ich nicht, im Normalbetrieb ist es noch nicht passiert.

Dennoch: Gibt es eine Möglichkeit, während des Schreibvorgangs im Timer einen threadfremden Zugriff zu erkennen? Alternativ müsste ich in der Vorlagedatei Javascript einsetzen, um die Veränderungen herbeizuführen, bin darin aber nicht sonderlich gut und habe es deswegen noch nicht probiert.

Mittlerweile konnte ich einen Screenshot der Meldung erstellen, der hängt an.

Und jetzt habe ich mal das HRESULT in die Suche eingegeben und wurde fündig:
https://stackoverflow.com/questions/2190390/how-to-fix-the-requested-resource-is-in-use-exception-from-hresult-0x800700a

Merkwürdig, dass die 'IsBusy'-Abfrage nicht funktionierte, war nämlich meine erste Idee. Also okay, wieder was dazu gelernt. damit dürfte sich das Thema erledigt haben. Danke für deine Hilfe!

Gehabt euch alle wohl, bleibt gesund - ...lypô
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von MoaByter am .
Attachments
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.317

beantworten | zitieren | melden

Wie Palladin007 schon schrieb, darfst du aus anderen Threads nicht direkt auf UI-Controls zugreifen. Abhilfe s. [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)
Trotzdem mußt du bei verschiedenen Threads immer passend synchronisieren (Stichwort: Race Condition)!
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.758
Herkunft: Düsseldorf

beantworten | zitieren | melden

Du kannst die ThreadId abrufen: Thread.CurrentThread.ManagedThreadId
Das in eine Watch packen, dann siehst Du immer, in welchem Thread Du gerade debuggst.
Es gibt noch andere Wege, das im Debugger sichtbar zu machen, doch das ist mMn. der einfachste Weg.

Wenn es mehrere Threads sind, musst Du die Aufrufe in den UI-Thread synchronisieren.
Wie das geht, hängt von dem UI-Framework ab, das Du nutzt, im Link von Th69 wird erklärt, wie.

Bei jedem UI-Framework sollte es aber eine SynchronizationContext-Implementierung geben, die das übernehmen kann, z.B. die Tasks in Verbindung mit async/await nutzen das.
Die statische SynchronizationContext.Current-Eigenschaft hat im UI-Thread dann die passende Implementierung, überall sonst steht da null drin - außer Du hast was Eigenes zugewiesen. Das Ding rufst Du dann im UI-Thread ab und gibst es für die Synchronisation an die jeweiligen Klassen weiter, die mit anderen Threads arbeiten.
Das hat den Charme, dass die Logik nichts vom verwendeten UI-Framework wissen muss, SynchronizationContext liegt nämlich in System.Threading.

Das ist natürlich kein Allheilmittel, aber nach dem, was ich bisher gelesen habe, eine mögliche Lösung.
private Nachricht | Beiträge des Benutzers
MoaByter
myCSharp.de - Member



Dabei seit:
Beiträge: 62
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Ist ein Timer denn ein anderer Thread?

Ich starte in der 'Form1' einen Timer, um die Prozesse zu entkoppeln, und von dort aus beschreibe ich den Browser. Wenn der dann abgelaufen ist, wird ein BackgroundWorker in einer eigenen Klasse gestartet, der verschiedene Webzugriffe durchführt und am Schluss über Invoke in den WebBrowser eine Zeile einträgt. Klingt verrückt, dass ich nicht den ReportProgress verwende, nur wird mir der zu groß - zuviele Tests, wer meldet und was getan werden soll usw...

Das funktioniert ja auch ganz gut und sehr flott, nur kam eben diese merkwürdige Meldung. Aber nun ist's ja wohl gelöst. Dank auch dir für deine Hilfe.

Viele Grüße, alles Gute - ...lypô
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von MoaByter am .
private Nachricht | Beiträge des Benutzers
MoaByter
myCSharp.de - Member



Dabei seit:
Beiträge: 62
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Uiuiui... Soweit bin ich mit meinen Kenntnissen noch nicht. Mit anderen Tasks hab' ich's mal versucht, war aber erfolglos, kommt also noch.

Ich notiere mal deinen Beitrag in meiner ToDo-Liste. Besonders den SynchonisationContext kenne ich nur namentlich. Das UI-Framework ist VisualStudio 2017, früher -express, jetzt wohl -common oder so ähnlich, die kostenlose Version also.

Ich habe jetzt erstmal genug Gedankenanstöße bekommen, die mich 'ne Weile beschäftigen werden. Da es so im Moment gut funktioniert, kann ich mich in Ruhe mit den anderen Dingen befassen.

Dir also auch recht herzlichen Dank, ich melde mich, wenn neue Fragen auftauchen.

Macht's gut, macht's besser - ...lypô
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.758
Herkunft: Düsseldorf

beantworten | zitieren | melden

Zitat
Ist ein Timer denn ein anderer Thread?
Die Timer-Implementierungen in System.Timers und System.Threading arbeiten beide in eigenen Threads, ja. Die Implementierung von WinForms arbeite meine ich mit dem UI-Thread.
Zitat
wird ein BackgroundWorker in einer eigenen Klasse gestartet
Der BackgroundWorker gehört in die Mottenkiste und wurde schon lange von den Tasks abgelöst.
Die Tasks machen das gleiche, nur dass es mit async/await in etwa wie normaler C#-Code aussieht, aber asynchron funktioniert, also weit übersichtlicher ist.
Zitat
Mit anderen Tasks hab' ich's mal versucht, war aber erfolglos, kommt also noch.
Das ist keine Entschuldigung ;)
Nur deswegen auf alte Technik aufzubauen, ist Arbeit in die falsche Richtung.
Zitat
Besonders den SynchonisationContext kenne ich nur namentlich
In den meisten Fällen braucht man den auch nicht.
Der wird erst dann spannend, wenn Du von irgendwo manuell zurück zum UI-Thread synchronisieren musst.

Der SynchronizationContext ist "nur" eine Abstraktion um den UI-Thread, normalerweise braucht man den nicht. Spannend wird er dann, wenn Du einen eigenständigen Thread (oder mehrere) unabhängig von der UI hast, aber zur UI synchronisieren musst.
Für alle "normalen" Operationen (z.B. Datenbankabfragen) reicht async/await aus.

Ich habe ihn deshalb erwähnt, weil die Nutzung des "direkten" Weges streng genommen eine Verletzung der Schichten-Architektur sein kann, der SynchronizationContext umgeht das Ganze.
Man muss nur darauf achten, dass man im UI-Thread ist, wenn man ihn abruft, danach reicht ein Post-Aufruf.
Zitat
jetzt wohl -common oder so ähnlich
"Community"
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.317

beantworten | zitieren | melden

Zitat von MoaByter
Das UI-Framework ist VisualStudio 2017, früher -express, jetzt wohl -common oder so ähnlich, die kostenlose Version also.
Mit UI-Framework ist "Windows Forms (WinForms)" oder WPF gemeint, du hast die Entwicklungsumgebung (IDE) genannt.
Aber aufgrund deiner verwendeten Klassen benutzt du wohl WinForms.
private Nachricht | Beiträge des Benutzers
MoaByter
myCSharp.de - Member



Dabei seit:
Beiträge: 62
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Ja, ich meinte System.Windows.Forms -> SWF. Mit WPF habe ich mich noch nicht beschäftigt.
private Nachricht | Beiträge des Benutzers
MoaByter
myCSharp.de - Member



Dabei seit:
Beiträge: 62
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Mit meinem Programm aktualisiere ich eine Webseite, d.h. ich erhalte Texte als PDF oder *.doc-Datei, das Programm formt diese passend um und lädt sie über ein dem Browser nachgebildetes Interface in eine Datenbank hoch. Das muss einwandfrei funktionieren - auch wenn's nur ein MiniJob ist, es ist 'n Job. Mit dem Backgroundworker tut's das, Aktualisierung auf Tasks dann, wenn ich mit den Task-Geschichten klar komme. Manches findet den Weg in mein Gehirn nicht so schnell. :-( Und das ist 'ne Entschuldigung ... für mich ... vorerst.

Ich nutze den SWF-Timer. Bei den anderen muss ich mal schauen, was die bieten.

Bedankt, gehabe dich wohl - ...lypô
private Nachricht | Beiträge des Benutzers
HansFred
myCSharp.de - Member



Dabei seit:
Beiträge: 48

beantworten | zitieren | melden

es heisst winforms und nicht swf. swf ist die abkürzung für shockwave flash.
private Nachricht | Beiträge des Benutzers
MoaByter
myCSharp.de - Member



Dabei seit:
Beiträge: 62
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

using System.Windows.Forms;
using SWF = System.Windows.Forms;

...

SWF.Timer tm2 = new SWF.Timer { Interval = 1 };

Deswegen...
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1.961
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Dir ist aber klar, dass du durch das erste using, direkt Timer als Klasse verwenden kannst ohne den unsinnigen SWF Namespace Ersatz oder?
Falls nicht, jetzt weißt du es.
Bitte nutzte solche Bezeichnungen/Namespace Alternativen nicht.
Außer dir kann nieman was mit den Bezeichnungen anfangen noch sind diese hilfreich.
Du solltest dir auch nochmal den Zweck von Namespaces anschauen.

T-Virus
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von T-Virus am .
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers