I have a solution and I thought I would post it in case anyone is interested.
First is that the class that implements the callback on the client needs the
CallbackBehavior attribute with the UseSynchronizationContext option turned
off. In other words:
[CallbackBehavior(UseSynchronizationContext = false)]
class Client : ITradeServiceCallback
{
private Form1 _frm;
public Client(Form1 frm)
{
_frm = frm;
}
public void OnTrade(string symbol, int ticks)
{
SendOrPostCallback addTradeDel = delegate
{
_frm.AddTrade(symbol, ticks);
};
_frm._context.Post(addTradeDel, null);
}
}
Notice in there that I store a reference to the form. This is because the
Form will store the SynchronizationContext for its GUI thread when it is
created. When my OnTrade method is invoked I tell that form's
SynchronizationContext to call a method using a delegate.
You can see in this code snippet where I grab the SynchronizationContext in
the form's constructor.
public partial class Form1 : Form
{
private Client c;
TradeServiceClient client;
// this will be called by the callback client so make it public
public SynchronizationContext _context;
public Form1()
{
InitializeComponent();
_context = SynchronizationContext.Current;
// create the callback object
c = new Client(this);
InstanceContext site = new InstanceContext(null, c);
// create the proxy object
client = new TradeServiceClient(site);
//create a unique callback address so multiple clients can run
on one machine
WSDualHttpBinding binding =
(WSDualHttpBinding)client.Endpoint.Binding;
string clientcallbackaddress =
binding.ClientBaseAddress.AbsoluteUri;
clientcallbackaddress += Guid.NewGuid().ToString();
binding.ClientBaseAddress = new Uri(clientcallbackaddress);
//Subscribe.
client.Subscribe();
}
Before I was using the Form's Invoke method to update the GUI. I thought
that would let the UI thread do its work. But it was blocking. This way
works. Now I have to see if I can figure out why this is the case. But at
least I have a working example.
That code would probably be cleaner if I used my form class as the callback
implementation but for whatever reason I decided to keep them seperate.
I posted the solution at the following URL if anyone cares.
http://www.suddethassoc.com/DuplexMethodhttp.zip I want to give credit to the folks at iDesign. It was by going through their
samples that I was able to figure this out.
[quoted text, click to view] "Jeff" wrote:
> I still have a lot to learn about WCF and I am hoping someone can point me in
> the right direction. I am using the wsDualHttpBinding binding to implement a
> publisher subscriber model. I have 3 projects set up in a solution - the
> host, a Console client, and a Winforms client.
>
> The Console client works as expected. But the Winforms client hangs when
> calls the method to publish data.
>
> If I run multiple instances of the winforms client the other instances get
> their callbacks. But the one that publishes the data hangs. It never returns
> from the Trade() method, which is the contract method I created to publish
> stock trades in this example. I am sure this is related to me not
> understanding something about the threading or instancing being used by WCF
> and how it relates to the GUI thread.
>
> I couldn't see a way to attach the source so I stuck in on a website here:
>
http://www.suddethassoc.com/DuplexMethod.zip >
> Any help would be appreciated.
>
> Jeff