I am currently writing a .Net application in c#, which has two main components:
- DataGenerator -a component generating a lot of data
- Viewer - a WPF application that is able to visualize the data that the generator creates
Those two components are currently two seperate projects in my solution. Furthermore, I am using the PRISM 4.0 framework in order to make modules out of those components.
Essentially, the DataGenerator generates a lot of data and sends out events using the EventAggregator from PRISM and the Viewer subscribes to these events and shows the data ready for the user.
Now my requirements have slightly changed and the two components will now run in their own application (but on the same computer). I would still like to have all the communication event-driven and I would also still like to use the PRISM framework.
My first thought was to use WCF for the communication between those two applications. However, there is one thing that makes life a bit harder:
- the DataGenerator has absolutely no knowledge about the Viewer (and no dependencies)
- the DataGenerator should still be working perfectly fine if we do not have viewer open, or if we close the viewer application.
- a lot of events are currently rising from the DataGenerator (using the EventAggregator): Is WCF efficient enough to handle lots of events in a very short amount of time?
Basically the data that all those events carry are very simple strings, integer and booleans. Could there be a more lightweight way of doing this without WCF?
Finally, it would be nice if the DataGenerator could send out these events and potentially more than one application subscribes to them (or none).
Any suggestions and hints are highly appreciated.
Thanks! Christian
EDIT 1
I am now creating two simple Console applications (one hosting the service and sending the messages, another one receiving the messages) using WCF and Callbacks (as has been suggested). I will add working code as soon as I get this working.
EDIT 2
Okay - Managed to get a simple program running! :) Thanks for your help, guys! Here is the code and a picture of where which classes are:
Let's start with the sender:
In my application, the sender contains the service interfaces and their implementations.
IMessageCallback is the callback interface:
namespace WCFSender
{
interface IMessageCallback
{
[OperationContract(IsOneWay = true)]
void OnMessageAdded(string message, DateTime timestamp);
}
}
ISimpleService is the service contract:
namespace WCFSender
{
[ServiceContract(CallbackContract = typeof(IMessageCallback))]
public interface ISimpleService
{
[OperationContract]
void SendMessage(string message);
[OperationContract]
bool Subscribe();
[OperationContract]
bool Unsubscribe();
}
}
SimpleService is the implementation of ISimpleService:
public class SimpleService : ISimpleService
{
private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>();
public void SendMessage(string message)
{
subscribers.ForEach(delegate(IMessageCallback callback)
{
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
{
callback.OnMessageAdded(message, DateTime.Now);
}
else
{
subscribers.Remove(callback);
}
});
}
public bool Subscribe()
{
try
{
IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
if (!subscribers.Contains(callback))
subscribers.Add(callback);
return true;
}
catch
{
return false;
}
}
public bool Unsubscribe()
{
try
{
IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
if (!subscribers.Contains(callback))
subscribers开发者_运维知识库.Remove(callback);
return true;
}
catch
{
return false;
}
}
}
In Program.cs (on the sender side), the Service is hosted and the messages are being send:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class Program : SimpleServiceReference.ISimpleServiceCallback, IDisposable
{
private SimpleServiceClient client;
static void Main(string[] args)
{
ServiceHost myService = new ServiceHost(typeof(SimpleService));
myService.Open();
Program p = new Program();
p.start();
Console.ReadLine();
}
public void start()
{
InstanceContext context = new InstanceContext(this);
client = new SimpleServiceReference.SimpleServiceClient(context, "WSDualHttpBinding_ISimpleService");
for (int i = 0; i < 100; i++)
{
client.SendMessage("message " + i);
Console.WriteLine("sending message" + i);
Thread.Sleep(600);
}
}
public void OnMessageAdded(string message, DateTime timestamp)
{
throw new NotImplementedException();
}
public void Dispose()
{
client.Close();
}
}
Furthermore, note that the service reference has been added to the Sender project!
Lets now get to the Receiver side:
As has already been done in the Sender, I added the Service Reference to the project.
There is only one class, Program.cs:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class Program : SimpleServiceReference.ISimpleServiceCallback, IDisposable
{
private SimpleServiceClient client;
static void Main(string[] args)
{
Program p = new Program();
p.start();
Console.ReadLine();
p.Dispose();
}
public void start()
{
InstanceContext context = new InstanceContext(this);
client = new SimpleServiceReference.SimpleServiceClient(context, "WSDualHttpBinding_ISimpleService");
client.Subscribe();
}
public void OnMessageAdded(string message, DateTime timestamp)
{
Console.WriteLine(message + " " + timestamp.ToString());
}
public void Dispose()
{
client.Unsubscribe();
client.Close();
}
}
The last thing remaining are the app.config files. On the client side, the app.config is automatically generated by adding the service reference. On the server side, I have slightly changed the config, however parts of it are also auto-generated by adding the service reference. Note that you need to do the changes before adding the service reference:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_ISimpleService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8732/Design_Time_Addresses/WCFSender/SimpleService/"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_ISimpleService"
contract="SimpleServiceReference.ISimpleService" name="WSDualHttpBinding_ISimpleService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
<behaviors>
<serviceBehaviors>
<behavior name="MessageBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WCFSender.SimpleService" behaviorConfiguration="MessageBehavior">
<endpoint address="" binding="wsDualHttpBinding" contract="WCFSender.ISimpleService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/WCFSender/SimpleService/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
IMPORTANT: I managed to implement these two very simple applications using the tutorials. The above code works for me and hopefully helps others to understand WCF callback. It is not extremely well-written code and should not be used entirely! It is just a simplistic example app.
Dont worry about performance, wcf can reach very high throughput if configured properly. Use callbacks for your events : http://www.switchonthecode.com/tutorials/wcf-tutorial-events-and-callbacks
Use WCF with callbacks, it is very efficient when configured properly.
Here are some benchmarks: http://msdn.microsoft.com/en-us/library/bb310550.aspx
Here is a good example of using callbacks: http://idunno.org/archive/2008/05/29/wcf-callbacks-a-beginners-guide.aspx
Use Microsoft StreamInsight 1.2. Use cases describes, that It can embed into the application, WCF service or both.
Read the MSDN Article abou StreamInsight 1.2:
Microsoft® StreamInsight is Microsoft’s Complex Event Processing technology to help businesses create event-driven applications and derive better insights by correlating event streams from multiple sources with near-zero latency.
Microsoft StreamInsight™ is a powerful platform that you can use to develop and deploy complex event processing (CEP) applications. Its high-throughput stream processing architecture and the Microsoft .NET Framework-based development platform enable you to quickly implement robust and highly efficient event processing applications. Event stream sources typically include data from manufacturing applications, financial trading applications, Web analytics, and operational analytics. By using StreamInsight, you can develop CEP applications that derive immediate business value from this raw data by reducing the cost of extracting, analyzing, and correlating the data; and by allowing you to monitor, manage, and mine the data for conditions, opportunities, and defects almost instantly.
By using StreamInsight to develop CEP applications, you can achieve the following tactical and strategic goals for your business:
Monitor your data from multiple sources for meaningful patterns, trends, exceptions, and opportunities.
Analyze and correlate data incrementally while the data is in-flight -- that is, without first storing it--yielding very low latency. Aggregate seemingly unrelated events from multiple sources and perform highly complex analyses over time.
Manage your business by performing low-latency analytics on the events and triggering response actions that are defined on your business key performance indicators (KPIs).
Respond quickly to areas of opportunity or threat by incorporating your KPI definitions into the logic of the CEP application, thereby improving operational efficiency and your ability to respond quickly to business opportunities.
Mine events for new business KPIs.
Move toward a predictive business model by mining historical data to continuously refine and improve your KPI definitions.
Additional info & samples can be found at CodePlex:
精彩评论