Laden...

Backgroundworker Kollisionsgefahr?

Erstellt von blackdynamic vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.136 Views
B
blackdynamic Themenstarter:in
51 Beiträge seit 2010
vor 12 Jahren
Backgroundworker Kollisionsgefahr?

Sehr geehrte Community,

ich stehe zur Zeit vor folgendem Problem:
Ich habe einen Service, der es mir ermöglicht Daten zu versenden.
Das senden der Daten würde ich gerne asynchron über einen Backgroundworker laufen lassen.
Es müssen von mehreren verschiedenen Stellen aus Daten gesendet werden können.

Nun zu meinen zwei Fragen:

  1. Ist die wahrscheinlichkeit groß, dass es dabei zu einer Kollision kommt?
  2. Wie könnte ich so eine Kollision verhindern? Am besten wäre wenn ich einem Thread sagen könnte: "Wenn gerade jemand anders Daten sendet, dann warte bis der damit fertig ist und fang dann erst an zu senden"

Ich würde mich freuen, wenn ihr mir helfen könnt.

Viele Grüße
blackdynamic

5.742 Beiträge seit 2007
vor 12 Jahren

Ist die wahrscheinlichkeit groß, dass es dabei zu einer Kollision kommt?

Das kommt ganz darauf an, wie dein Programm aufgebaut ist.
Allerdings muss die Wahrscheinlichkeit nicht zwangsläufig groß sein, dass es zu "Kollisionen" (und damit zu Bugs) kommt; es reicht schon eine > 0 😉

Wie könnte ich so eine Kollision verhindern? Am besten wäre wenn ich einem Thread sagen könnte: "Wenn gerade jemand anders Daten sendet, dann warte bis der damit fertig ist und fang dann erst an zu senden"

Das könntest du zwar mithilfe von AutoResetEvents realisieren, wovon ich aber eher abraten würde.
Verwende lieber einen dedizierten Sendethread und eine threadsichere Queue (z.B. die BlockingCollection<T> oder SyncQueue <T> - Eine praktische Job-Queue ), in die du alle zu sendenden Daten legst und die der Sendethread abarbeitet.

156 Beiträge seit 2010
vor 12 Jahren
  1. Ist die wahrscheinlichkeit groß, dass es dabei zu einer Kollision kommt?

beim Senden mit TCP hatte ich bisher noch keine Probleme ... Probleme gibt es aber sicher beim Empfang von UDP Daten

  1. Wie könnte ich so eine Kollision verhindern? Am besten wäre wenn ich einem Thread sagen könnte: "Wenn gerade jemand anders Daten sendet, dann warte bis der damit fertig ist und fang dann erst an zu senden"

Monitoring ... am einfachsten mit


public class Sometimes {
    private static Object monitor4send = new Object();
    // ...
    public void sned(byte[] data) {
        lock(monitor4send) {
            // Daten über Socket senden
        }
    }
}

hand, mogel

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo mogel,

das lock blockiert aber den aufrufenden Threads unnötigerweise bis alle schon anstehenden Request abgearbeitet (und auch die eigenen Daten gesendet) wurden. Da ist der Vorschlag mit den SyncQueue schon sinnvoller.

herbivore

B
blackdynamic Themenstarter:in
51 Beiträge seit 2010
vor 12 Jahren

Vielen Dank für eure schnellen Antworten. 😃

Der Service schmeisst zusätzlich noch Events, wenn er selbst Daten empfangen hat.
Kann das in Kombination mit den SyncQueue zu Komplikationen führen?

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo blackdynamic,

naja, Synchronisation ist fast nie ein leichtes Geschäft und ohne genau Kenntnis der Umstände, der Zugriffspfade und der Abhängigkeiten kann man da keine verbindliche Antwort geben. Und selbst wenn man das alles weiß, ist es ziemlich schwierig. Das muss du schon selber analysieren. Und dazu musst du sehr genau wissen, was du tust. Einen ersten Einstieg findest du in [Artikel] Multi-Threaded Programmierung. Im Thread SyncQueue <T> - Eine praktische Job-Queue findest du ja schon mal ein Beispiel dafür, welche wenig naheliegenden Situationen man bedenken muss. Das bedeutet auch, dass weit mehr lernen muss, als man aus einen einzigen Artikel lernen kann.

herbivore

B
blackdynamic Themenstarter:in
51 Beiträge seit 2010
vor 12 Jahren

Vielen Dank 😃

B
blackdynamic Themenstarter:in
51 Beiträge seit 2010
vor 12 Jahren

Ich verwende zur Zeit asynchrone Methodenaufrufe, die denen hier im Kapitel 5.5 ([Artikel] Multi-Threaded Programmierung) sehr ähneln.

Das heisst, das Senden der Daten soll ebenfals in so einem asnychronen Methodenaufruf erfolgen.

Der Service zum senden der Daten würde der asynchronen Methode als request Parameter übergeben werden. Dürfte ich von meiner asynchronen Methode aus, die sich hinter dem asynchronen Proxy befindet, auf eine statische SyncQueue zugreifen, die sich in dem ViewModel befindet das die asynchrone Methode aufruft?
Auch in Bezug auf das MVVM Pattern..

Ich hoffe ihr versteht was ich meine 😃

Viele Grüße

*edit -> Oder wie wäre es, wenn ich die SyncQueue in das request objekt einbauen würde? Wäre das "sauberer"?

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo blackdynamic,

mach es so wie du schreibst, damit meine ich den Teil:

Der Service zum senden der Daten

Erstell also einen eigenen Service zum Senden der Daten* und in diesem ist die SyncQueue. Ins ViewModel gehört das Senden nicht, aber das VM enqueued neue Sendeaufträge über einen Methodenaufruf des SendService (und wird ggf. per Event vom Service benachrichtigt dass etwas versendet wurde).

* wie du siehst richtet sich das Ganze ziemlich genau nachdem wie du es auch sprachlich formulierst. Oder anders: Separation of Concerns (SoC)

Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 1.2.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo blackdynamic,

Dürfte ich von meiner asynchronen Methode aus, [...] auf eine statische SyncQueue zugreifen

der Zugriff auf die SyncQueue kann von allen Threads und allen Stellen aus erfolgen, denn wie der Name sagt ist die ja synchronisiert. Das einzige Problem mit der Queue selber, das man sich einhandeln kann, ist ein Thread, der Dequeue aufruft und dauerhaft blockiert, wenn es keinen anderen Thread gibt, der Enqueue aufruft. Aber ansonsten kann es beliebig viele Producer und beliebig viele Consumer geben, und sogar beliebig viele Threads, die beides gleichzeitig sind. Das kann die Queue ab.

Das bedeutet aber nicht, dass automatisch auch der Zugriff auf die Daten, die in die Queue gestellt werden, synchronisiert ist. Deshalb sollte ein Producer, sobald er die Daten eingestellt hat, nicht mehr darauf zugreifen und ein Consumer sollte seinerseits erst mit dem Zugriff auf die Daten beginnen, nachdem er sie aus der Queue geholt hat. Das gilt sowohl für die Einträge in der Queue selbst als auch (rekursiv) für alle Objekte, auf die aus den Einträgen verwiesen wird.

herbivore