using System;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading;
using System.IO;
using System.Xml.Serialization;
namespace SilverlightPushClient
{
public interface IProcessor
{
void ProcessData(object receivedData);
}
public class PushDataReceiver
{
SynchronizationContext _UiThread = null;
public IProcessor Client { get; set; }
public string ServiceUrl { get; set; }
public string Action { get; set; }
public string ActionData { get; set; }
public PushDataReceiver(IProcessor client, string url, string action, string actionData)
{
Client = client;
ServiceUrl = url;
Action = action;
ActionData = actionData;
_UiThread = SynchronizationContext.Current;
}
public void Start()
{
// Instantiate the binding and set the time-outs
PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding()
{
PollTimeout = TimeSpan.FromSeconds(10),
InactivityTimeout = TimeSpan.FromMinutes(1)
};
// Instantiate and open channel factory from binding
IChannelFactory<IDuplexSessionChannel> factory =
binding.BuildChannelFactory<IDuplexSessionChannel>(new BindingParameterCollection());
IAsyncResult factoryOpenResult =
factory.BeginOpen(new AsyncCallback(OnOpenCompleteFactory), factory);
if (factoryOpenResult.CompletedSynchronously)
{
CompleteOpenFactory(factoryOpenResult);
}
}
void OnOpenCompleteFactory(IAsyncResult result)
{
if (result.CompletedSynchronously)
return;
else
CompleteOpenFactory(result);
}
void CompleteOpenFactory(IAsyncResult result)
{
IChannelFactory<IDuplexSessionChannel> factory =
(IChannelFactory<IDuplexSessionChannel>)result.AsyncState;
factory.EndOpen(result);
// The factory is now open. Create and open a channel from the channel factory.
IDuplexSessionChannel channel =
factory.CreateChannel(new EndpointAddress(ServiceUrl));
IAsyncResult channelOpenResult =
channel.BeginOpen(new AsyncCallback(OnOpenCompleteChannel), channel);
if (channelOpenResult.CompletedSynchronously)
{
CompleteOpenChannel(channelOpenResult);
}
}
void OnOpenCompleteChannel(IAsyncResult result)
{
if (result.CompletedSynchronously)
return;
else
CompleteOpenChannel(result);
}
void CompleteOpenChannel(IAsyncResult result)
{
IDuplexSessionChannel channel = (IDuplexSessionChannel)result.AsyncState;
channel.EndOpen(result);
// Channel is now open. Send message
Message message =
Message.CreateMessage(channel.GetProperty<MessageVersion>(),
Action , ActionData);
IAsyncResult resultChannel =
channel.BeginSend(message, new AsyncCallback(OnSend), channel);
if (resultChannel.CompletedSynchronously)
{
CompleteOnSend(resultChannel);
}
//Start listening for callbacks from the service
ReceiveLoop(channel);
}
void OnSend(IAsyncResult result)
{
if (result.CompletedSynchronously)
return;
else
CompleteOnSend(result);
}
void CompleteOnSend(IAsyncResult result)
{
IDuplexSessionChannel channel = (IDuplexSessionChannel)result.AsyncState;
channel.EndSend(result);
}
void ReceiveLoop(IDuplexSessionChannel channel)
{
// Start listening for callbacks.
IAsyncResult result = channel.BeginReceive(new AsyncCallback(OnReceiveComplete), channel);
if (result.CompletedSynchronously) CompleteReceive(result);
}
void OnReceiveComplete(IAsyncResult result)
{
if (result.CompletedSynchronously)
return;
else
CompleteReceive(result);
}
void CompleteReceive(IAsyncResult result)
{
//A callback was received so process data
IDuplexSessionChannel channel = (IDuplexSessionChannel)result.AsyncState;
try
{
Message receivedMessage = channel.EndReceive(result);
// Show the service response in the UI.
if (receivedMessage != null)
{
string text = receivedMessage.GetBody<string>();
_UiThread.Post(Client.ProcessData, text);
}
ReceiveLoop(channel);
}
catch (CommunicationObjectFaultedException exp)
{
_UiThread.Post(delegate(object msg) { System.Windows.Browser.HtmlPage.Window.Alert(msg.ToString()); }, exp.Message);
}
}
void OnCloseChannel(IAsyncResult result)
{
if (result.CompletedSynchronously)
return;
else
CompleteCloseChannel(result);
}
void CompleteCloseChannel(IAsyncResult result)
{
IDuplexSessionChannel channel = (IDuplexSessionChannel)result.AsyncState;
channel.EndClose(result);
}
}
}