How to make a call to my WCF service asynchronous? - c#

I have a WCF service that I call from a windows service.
The WCF service runs a SSIS package, and that package can take a while to complete and I don't want my windows service to have to wait around for it to finish.
How can I make my WCF service call asynchronous? (or is it asynchronous by default?)

All your needs will be satisfied in the following articles from MSDN:
Implementing an Async Service Operation
Calling WCF Service Async
Designing Service Contracts

On Visual Studio 2010, on the Add Service Reference > click Advanced button > check the Generate Asynchronous Operations checkbox.
After doing so, the Async operations will be added and be available for your use.

Service side:
[ServiceContract]
public interface IMyService
{
[OperationContract]
bool DoWork(int i);
}
Client side:
[ServiceContract(Name = nameof(IMyService))]
public interface IMyServiceClient : IMyService
{
[OperationContract]
Task<bool> DoWorkAsync(int i);
}

the WCF Proxy inside of your client (Windows Service?) needs to be specified at creation that you wish to have Asynchronous operations available.
You can modify an existing WCF Proxy by right clicking on it and choosing 'Configure Service Reference' From here you just need to check the tick box next to 'Generate asynchronous operations'
Ok so that is the WCF Proxy side of things taken care of.
Now you need to use APM (Asynchronous Programming Model) with the Proxy inside of your client.

Related

Show server counter on GUI while still in progress

My question is pretty simple, but I got lost somehow.
I have a project including ClientProject and ServerProject (WCF service application) contains my Service class and its interface.
The service runs method with few iterations.
All I need to do is to show on GUI the service's number of iteration on real time,
so that the user will be able to be aware to service activity state while running.
I've seen examples of declaring a delegate ServerEventHandler on service,
and registration to that event on client side.
For example:
ServiceProject:
public delegate void ServerEventHandler(object sender, EventArgs e);
public event ServerEventHandler ServerEvent; <br/><br/>
ClientProject:
public Client(Server s)
{
s.ServerEvent += new Server.ServerEventHandler(Subscribe);
}
But I can not figure out how can I implement it on my WCF project, since my client and server are separated projects so that the only way I can get my ServiceProject values on my ClientProject is through its ServiceReference.
I can't understand how can the client have the service instance, and how can it access the ServerEvent property through it.
What am I missing?
Do I have to mention anything on my contract? Or is there any other way to implement it?
I'd be thankful If you'll be able to help me..
you can implement WSDualHttpBinding which allows you to define callback contract
WCF comes with async variance for each operation..you can call async operation on Callback Operation so server process will keep running....Even callback will have DataContract so just create DataContract class which will hold all values which you want to show in UI..Imagine callback as Service exposed by client so that Server can notify client by calling appropriate operation.

Implement a WCF-Mock and the endpoint before implementing the real service

Background:
I have to extend an application which already uses WCF services with another WCF Service. One of these already existing services should call the new WCF service. Now the requirements are that the future service should be mocked and the connection between this two services should be tested (not a unit test) with this mock service before implementing the real service. The mock service should write the received parameters to a file.
Goal:
This means the endpoint in the existing WCF service is implemented and ready (except for some changes in the config).
My approaches:
Implement own mock service (Blog post) or use a mock framework (WCFMock) which mocks a already defined interface.
Problems:
The call of the mock service looks different and I have to change the code of the endpoint after the implementation of the real service.
My Question:
Is it possible to mock or fake a WCF service (without real web call) and implement the endpoint which will also work with the real WCF service after changing the config?
Yes. You will need to create a class that acts as an intermediary for the WCF service client calls and then either loads an actual client or your mock service depending on some value (probably a config value). This way, the dependencies in your code are handled such that all you need to do is change a flag in order to switch implementations.
The biggest constraint on this working is that the service interface must be available to the client to implement.
Basic idea is as follows:
public class ServiceFacade : IMyWCFService
{
private IMyWCFService _clientImplementation;
public ServiceFacade()
{
_clientImplementation = (Settings.Default.UseMockService == true) ? new MockWCFServiceClient() : new MyWcfServiceClient();
}
#region IMyWCFService implementation
public int MyServiceCall()
{
return _clientImplementation.MyServiceCall();
}
#endregion
}

Having WCF service proxy configurable

I am writing a basic WPF GUI to connect to a WCF service and consume an interface. So far I have connected to the test system by creating a service reference, putting in the URI for the test service I want to consume, it finds the interface and creates the proxy via service reference for me.
What I want this to do when you run the GUI app is for the user to be able to pick an environment - development, test or production and for the GUI to then connect to the appropriate WCF service depending on the environment selected.
How can I do this?
You can overwrite the Endpoint like this:
client.Endpoint.Address = new EndpointAddress(GetAddressForCurrentMode())
The other way you could to it, is to write a method, maybe an extension method, that accepts the service contract and the implementation class. Further more it either accepts a configuration name, or an endpoint:
public static TClient GetServiceClient<TClient, TContract>(string endpoint)
where TClient : ClientBase<TContract>
{
// Construct client
}
To construct the client, use one of BaseClient<T> overloads (from MSDN).
To then consume the client, just use the method above as normal:
using(var client = ServiceInterop.
GetServiceClient<MyClient, IMyContract>("http://foo.bar"))
{
// Consume client
}

Asynchronously consume synchronous WCF service

I’m currently in the process of migrating a client application over to .NET 4.5 to make use of async/await. The application is a client for a WCF service which currently offers only synchronous services. I am wondering now, how should I asynchronously consume this synchronous service?
I am using channel factories to connect to the WCF service, utilizing a service contract that is shared between both server and client. As such, I cannot use the auto-generation from VisualStudio or svcutil to generate asynchronous client proxies.
I have read this related question which is about whether to wrap the synchronous call on the client-side using Task.Run, or whether to extend the service contract with async methods instead. The answer suggests that having “real” asynchronous methods offered by the server is better for the client performance as no thread will have to actively wait for the service call to finish. This does make a lot of sense to me, and it would mean that the synchronous calls should be wrapped on the server-side.
On the other hand, Stephen Toub discorages doing this in general in this blog post. Now, he does not mention WCF there, so I am not sure if this just applies to libraries that run on the same machine, or if it also applies to things that run remotely, but where the introduction of asynchronicity has an actual impact on the connection/transfer.
And after all, as the server does not actually work asynchronously anyway (and likely won’t for another while), some threads will always have to wait: Either on the client or on the server. And that does also apply when consuming the services synchronously (currently, the client waits on a background thread to keep the UI responsive).
Example
To make the problem more clear, I have prepared an example. The full project is available for download here.
The server offers a synchronous service GetTest. This is the one that currently exists, and where the work happens—synchronously. One option would be to wrap this in an asynchronous method, for example using Task.Run, and offer that method as an additional service in the contract (requiring the contract interface to be expanded).
// currently available, synchronous service
public string GetTest() {
Thread.Sleep(2000);
return "foo";
}
// possible asynchronous wrapper around existing service
public Task<string> GetTestAsync() {
return Task.Run<string>(() => this.GetTest());
}
// ideal asynchronous service; not applicable as work is done synchronously
public async Task<string> GetTestRealAsync() {
await Task.Delay(2000);
return "foo";
}
Now, on the client-side, this service is created using a channel factory. That means I only have access to the methods as defined by the service contract, and I especially don’t have access to asynchronous service methods unless I explicitely define and implement them.
Depending on which methods are now available, I have two options:
I can asynchronously call the synchronous service by wrapping the call:
await Task.Run<string>(() => svc.GetTest());
I can asynchronously call the asynchronous service directly, which is provided by the server:
await svc.GetTestAsync();
Both works fine, and will not block the client. Both methods involve busy waiting on some end: Option 1 waits on the client, which is equivalent to what has been done before in a background thread. Option 2 waits on the server by wrapping the synchronous method there.
What would be the recommended way to make a synchronous WCF service async-aware? Where should I perform the wrapping, on the client or on the server? Or are there better options to do this without having to wait anywhere, i.e. by introducing “real” asynchronicity on the connection—like the generated proxies do?
The client side and server side are totally separate from an async standpoint, they do not care about each other at all. You should have your sync function on your sever and only the sync function on your server.
If you want to do it "right", on the client you will not be able to reuse the same interface for your generating your channel factory as the interface that is used to generate the server.
So your server side would look like this
using System.ServiceModel;
using System.Threading;
namespace WcfService
{
[ServiceContract]
public interface IService
{
[OperationContract]
string GetTest();
}
public class Service1 : IService
{
public string GetTest()
{
Thread.Sleep(2000);
return "foo";
}
}
}
and your client side would look like this
using System;
using System.Diagnostics;
using System.ServiceModel;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SandboxForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var button = new Button();
this.Controls.Add(button);
button.Click += button_Click;
}
private async void button_Click(object sender, EventArgs e)
{
var factory = new ChannelFactory<IService>("SandboxForm.IService"); //Configured in app.config
IService proxy = factory.CreateChannel();
string result = await proxy.GetTestAsync();
MessageBox.Show(result);
}
}
[ServiceContract]
public interface IService
{
[OperationContract(Action = "http://tempuri.org/IService/GetTest", ReplyAction = "http://tempuri.org/IService/GetTestResponse")]
Task<string> GetTestAsync();
}
}
If your server-side API can be naturally async (like your Task.Delay example, rather than the Task.Run wrapper), declare it as Task-based in the contract interface. Otherwise, just leave it synchronous (but don't use Task.Run). Do not create multiple endpoints for the sync and async versions of the same method.
The generated WSDL remains the same for async and sync contract APIs, I just found out that myself: Different forms of the WCF service contract interface. Your clients will keep running unchanged. By making your server-side WCF method asynchronous, all you do is improve the service scalability. Which is a great thing to do, of course, but wrapping a synchronous method with Task.Run would rather hurt the scalability than improve it.
Now, the client of your WCF service doesn't know if the method is implemented as synchronous or asynchronous on the server, and it doesn't need to know that. The client can call your method synchronously (and block the client's thread) or it can call it asynchronously (without blocking the client's thread). In either case, it won't change the fact that the SOAP response message will be sent to the client only when the method has fully completed on the server.
In your test project, you're trying to exposes different versions of the same API under different contract names:
[ServiceContract]
public interface IExampleService
{
[OperationContract(Name = "GetTest")]
string GetTest();
[OperationContract(Name = "GetTestAsync")]
Task<string> GetTestAsync();
[OperationContract(Name = "GetTestRealAsync")]
Task<string> GetTestRealAsync();
}
This doesn't really make sense, unless you want to give your client an option to control if the method runs synchronously or asynchronously on the server. I cannot see why you would want this, but even if you have your reason, you'd be better off controlling this via a method argument and a single version of the API:
[ServiceContract]
public interface IExampleService
{
[OperationContract]
Task<string> GetTestAsync(bool runSynchronously);
}
Then, in the implementation your could do:
Task<string> GetTestAsync(bool runSynchronously)
{
if (runSynchronously)
return GetTest(); // or return GetTestAsyncImpl().Result;
else
return await GetTestAsyncImpl();
}
#usr explains this in great details here. To sum up, it is not like the WCF service calls back your client to notify about the completion of the async operation. Rather, it simply sends back the full SOAP response using the underlying network protocol when it's done. If you need more than that, you could use WCF callbacks for any server-to-client notifications, but that would span the boundaries of a single SOAP message.
This isn't horrible: https://stackoverflow.com/a/23148549/177333. You just wrap your return values with Task.FromResult(). You have to change the service side, but it's still synchronous and you're not using an extra thread. That changes your server-side interface which can still be shared with the client so it can wait asynchronously. Otherwise it looks like you have to maintain separate contracts on server and client somehow.

How can I run a WCF service constructor once for all clients when it's InstanceContextMode is set to PerSession?

How can I run the code in the constructor of a WCF Service only once when the ServiceBehaviorAttribute.InstanceContextMode is set to PerSession?
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.PerSession,
ConcurrencyMode = ConcurrencyMode.Single)]
public class SomeService : ISomeService
{
public SomeService()
{
this.RunThisOnceForAllClients();
}
private void RunThisOnceForAllClients() { }
}
Or, how can I make a method run automatically once the WCF Service is running but it will only run once for all client calls?
Please help. Thanks in advance.
I deploy my WCF Service using a Managed Windows Service. My code is in C#. Framework is in .NET 4. Project is build in Visual Stuido 2010 Professional. The service is consumed by a Windows Forms Application. In case you wonder on why do I need to do it like this, I need to execute an Uploader method that will upload the database of the service to another service, but it will be executed in a certain time so I put it in another thread that will always run as long as the service is running.
Why not run this operation just before you host the WCF Service in your windows service so it can be ready as soon as the WCF Service goes online. You can get from the running thread an event that it is finished and then deploy the WCF Service.
You need to write a service behavior or an endpoint behaviour. In this behaviour call the function at first call from a client and set a variable to true and store it in some permament memory or file location.
You may have a look at the following msdn article about Extending WCF
Use a static constuctor? It will be called once when(before) any action with that class is taken in your code.

Categories