2016-08-05 11 views
1

Ich versuche, meinen Kopf darum herumzuwerfen, warum ein Windows-Formular, das einen Callback implementiert, nicht funktioniert.Callbacks auf SynchronizationContext

Was ich versuche zu tun:

  • wird eine Taste gedrückt und ein Dienst aufgerufen wird.
  • Der Service zum Formular ruft zurück (die Funktion hat IsOneWay = true)
  • Das Formular Updates GUI entsprechend funktioniert

UseSynchronizationContext auf falschen und ruft Invoke auf die GUI-Elemente mit:

[CallbackBehavior(UseSynchronizationContext = false)] 
public class DeliveryClient : System.Windows.Forms.Form, ICallback 
{   
     public void ServiceCallback(string system, string state, string extraInfo) 
     { 
      if (state == "start") 
      { 
       Invoke((MethodInvoker)delegate { picBox.Visible = true; }); 
      } 
      else 
      { 
       Invoke((MethodInvoker)delegate { picBox.Visible = false; }); 
      } 
     } 
} 

Aber UseSynchronizationContext = true und direkt die Mitglieder Aufruf nicht:

[CallbackBehavior(UseSynchronizationContext = true)] 
public class DeliveryClient : System.Windows.Forms.Form, ICallback 
{   
     public void ServiceCallback(string system, string state, string extraInfo) 
     { 
      if (state == "start") 
      { 
       picBox.Visible = true; 
      } 
      else 
      { 
       picBox.Visible = false; 
      } 
     } 

Weder SyynchronizationContext buchstäblich

SynchronizationContext.Current.Send(_=> picBox.Visible = true, null); 

Sollte die zweite und die dritte Version arbeitet auch nicht mit? Der Rückruf wird OneWay genannt, so dass der Dienst nach dem Rückruf fortgesetzt wird.

Antwort

1

Ist Ihre Form Klasse wirklich die Umsetzung Ihres WCF-Service-Client-Callback, als WCF weiß es (das heißt nicht nur etwas, das Sie von dem WCF-Client übertragen)? Wenn nicht, dann haben Sie das [CallbackBehavior] Attribut an die falsche Stelle gesetzt. Da die Dokumentation heißt es:

Die CallbackBehaviorAttribute muss auf die Klasse angewendet werden, die den Vertrag Rückruf implementiert

Wenn es die Umsetzung Ihrer Client-Rückruf ist, dann ohne eine gute Minimal, Complete, and Verifiable code example Ich fürchte, ich wäre nicht in der Lage zu sagen, warum das Attribut nicht den erwarteten Effekt hat. Aber ich wäre in der Lage zu sagen, dass, wenn das der Fall ist, Ihr Code schlecht entworfen ist. Die Kombination Ihrer Benutzeroberfläche mit der Callback-Implementierung Ihres Service-Clients verstößt gegen eine Reihe von OOP-Prinzipien für einen gesicherten Code, aber am wichtigsten ist das Separation of Concerns-Prinzip.

Soweit geht:

SynchronizationContext.Current.Send(_=> picBox.Visible = true, null); 

Das ist nicht, wie Sie SynchronizationContext verwenden sollten. Die Current-Eigenschaft gibt den Kontext für den aktuell laufenden Thread zurück. Zu dem Zeitpunkt, zu dem Sie Send() aufrufen müssen, ist es zu spät, den Kontext abzurufen. Sie müssen SynchronizationContext.Current speichern, wenn Sie Ihr Objekt in dem Thread erstellen, in dem Delegaten, die von Send() aufgerufen werden, ausgeführt werden sollen (und natürlich muss dieser Thread einen nützlichen Kontext haben, wie er im Haupt-UI-Thread eines Winforms-Programms gefunden wird)).

Wenn die oben genannten Informationen Ihnen nicht genügend Informationen liefern, um Ihren Code zum Laufen zu bringen, verbessern Sie die Frage, indem Sie einen guten MCVE bereitstellen, der das Problem zuverlässig reproduziert.

+0

das Callback-Verhalten ist richtig platziert ja, das Formular implementiert den Rückruf.Ich werde versuchen, den SynContext jetzt speichern – Laurijssen

+0

In der Tat, die Speicherung der SynContext nach InitializeComponent funktioniert – Laurijssen

+0

Ich stimme nicht mit dem sep von Bedenken tatsächlich. Ein Formular, das einen Callback implementiert, dessen einziger Zweck es ist, das Formular zu aktualisieren, sieht für mich in Ordnung – Laurijssen