Performance issue on WCF Console Application - c#

There is a WCF service that is hosted in a .Net Console application. The client creates a duplex channel to the service that has a callback. It calls the service in this way:
var task = Task<object>.Factory.FromAsync(clientRay.Proxy.BeginCalc, clientRay.Proxy.EndCalc, lst_RaySrvcDetails, state);
And here is the Main method of the service Console app:
static void Main(string[] args)
{
ServiceHost srvcHost = new ServiceHost(serviceInstance, uriBase);
//
//Here the service is hosted
//
while(true)
{
;
}
}
And the MyService.cs receives the call in the below method:
public IAsyncResult BeginCalc(List<MBSWaldram.DataAccessLayer.Framework.ServiceDetails> input,
AsyncCallback callback, object state)
{
calcInput = input;
// Create a task to do the work
var task = Task<object>.Factory.StartNew(this.CalcTasks, state);
return task.ContinueWith(res => callback(task));
}
Now the CalcTasks method, where the actual task is run, is showing less performance compare to have it on a WCF Windows Form application. One of the reason I can think of is the way I have used while(true){;} infinite loop so that the application doesn't terminates and waits for the call from the client. Not sure this the best of doing it. For some reason I can't use Windows Form Application.
I appreciate if anyone could shed some light in why there is a performance issue here.
Thanks.

while (true) {;} is really unlucky construction. In Console application take Console.ReadLine() instead. The application will wait until Enter press.

Related

Service windows and Async task

I am pretty new to windows service and I am trying to install a service to run some code (that I did not write).
This code runs without problem ( not in service mode) but when I install the service and try to run the service I have a timeout Error 1053 (The Service did not Respond to the Start or Control Request in a Timely Fashion).
I tried to set the ServicePipeTimeout to a higher value and install my service in release mode but that does not change anything.
After some investigations and prints I get an error with the main function Static Async Task()
So I am asking myself if maybe there is an incompatibility between Async and service ?
For example Maybe this kind of code executed at the beginning, could provoke timeout I get when I start my service: (I just wanted to know if async and service was compatible to help me in my search).
static void Main(string[] _)
{
MainAsync().Wait();
}
private static async Task MainAsync()
{
TimeSpan timeSpan = new TimeSpan(0, 0, 30);
using (SftpWatcher watcher = new SftpWatcher(mailServer, mailSender, mailName, mailDestination, ...)
{
await watcher.Start(timeSpan);
}
}

SignalR issue with invoking server method from onreceived method

I have following SignalR code for desktop client:
_hub.On<String>("Ping",(string s) =>
{
Console.WriteLine(s + " from MainHub ");
_hub.Invoke("Acknowledge","Say Hello to MainHub");
});
I have Ping and Acknowledge method on Hub.
But
_hub.Invoke("Acknowledge","Say Hello to MainHub");
is not firing properly from desktop client.
How to write this code properly?
As per this Link
Currently in the .NET client we serialize invoking user callbacks upon receiving messages from the server using a TaskQueue. This includes callbacks registered using HubProxy.On or continuations after HubProxy.Invoke.
If these callbacks block, especially blocking waiting on result from another callback, the receive dispatch queue will simply stop (deadlock).
We should detect this condition and trace an error when it occurs (Connection.OnError).
We could do this in the TaskQueue itself (with an optional flag that enables it of course) that makes it essentially monitor itself, using an async loop started on the first enqueue that checks if the task currently running is the same as what was running on the last interval. If so, log the error.
Now I have managed to fix this issue by a quick but dirty solution. I know this is not the way to fix this issue, but I dont have any choices other than this. Other solution better than this is higly appreciated.
Threading.Timer tmr= new Threading.Timer(new TimerCallback(Acknowledge),null, 0, Timeout.Infinite);
private void Acknowldege(object state)
{
if(SignalRIsReady)//check if signalr is ready
{
_hub.Invoke("Acknowledge","Say Hello to MainHub");
tmr.Change(Timeout.Infinite, Timeout.Infinite);//wait until next event occurs
}
}
_hub.On<String>("Ping",(string s) =>
{
Console.WriteLine(s + " from MainHub ");
tmr.Change(50, Timeout.Infinite);// call callback after 50ms
});
Another Solution I have managed is using configureawait. Following is the solution:
_hub.On<String>("Ping",async(string s) =>
{
Console.WriteLine(s + " from MainHub ");
await Task.Run(async()=>{
_hub.Invoke("Acknowledge","Say Hello to MainHub");
}).ConfigureAwait(false);//this will run the task to seperate thread, unblocking the parent thread
});

Logic for Windows Services & Getting Updates

I developed a Windows service using vb.net which does the following using OnStart Even...
Grabs all Entries from a SQL Table
Creates Schedules from returned rows
it works fine, schedules fire on their time and stuff.
Problem: Whenever I have to ADD a new row to my Table, I have to restart the Service, So it can Grab the Newly created rows. This is causing problems for me...there could be a task which is running already and restarting service might break the system.
So what is the best way to handle this? Can the new rows be loaded into Service without a restart?
Thanks
Use the concept of Polling into the Database. Use the System.Threading.Timer class, set some interval after which a callback method will be invoked and that will be responsible to Poll the Database for new entries.
This OnStart was provided here by Marc Gravell:
public void OnStart(string[] args) // should this be override?
{
var worker = new Thread(DoWork);
worker.Name = "MyWorker";
worker.IsBackground = false;
worker.Start();
}
void DoWork()
{
// do long-running stuff
}
Note that OnStart can launch multiple threads or the first thread started may be used to start additional threads as needed. This allows you to set up either database polling or a thread that waits on a message queue for data.
A useful tip:
Adding a Main to your service allows you to run it as a console application in Visual Studio. This greatly simplifies debugging.
static void Main(string[] args)
{
ServiceTemplate service = new ServiceTemplate();
if (Environment.UserInteractive)
{
// The application is running from a console window, perhaps creating by Visual Studio.
try
{
if (Console.WindowHeight < 10)
Console.WindowHeight = 10;
if (Console.WindowWidth < 240) // Maximum supported width.
Console.WindowWidth = 240;
}
catch (Exception)
{
// We couldn't resize the console window. So it goes.
}
service.OnStart(args);
Console.Write("Press any key to stop program: ");
Console.ReadKey();
Console.Write("\r\nInvoking OnStop() ...");
service.OnStop();
Console.Write("Press any key to exit: ");
Console.ReadKey();
}
else
{
// The application is running as a service.
// Misnomer. The following registers the services with the Service Control Manager (SCM). It doesn't run anything.
ServiceBase.Run(service);
}
}

How to react instantly to Internet Connectivity changes with Async operations?

In my C# Windows Forms application , I retrieve some data from WebServices over the Internet. Refresh every second
It works as asynchronous operations and works well but whenever application gets disconnected from Internet, it shows an exception, and when it reconnects to the Internet, program should work automatically and immediately.
Currently, the program takes more then one minute to start working again, and I would like the exception to be ignored when connection drops.
it refreshed every second , it mean there are plenty of threads running at same time and
when they all done , then it comes to connecting
What solution i can use so my programs runs ASAP when internet connects?
public void loadbalance()
{
try { //Get Data from Internet }
catch { }
}
delegate void loadbalancedelegate();
public void loadBalanceAsync()
{
loadbalancedelegate worker = new loadbalancedelegate(loadbalance);
AsyncCallback LoadbalnceCallBack = new AsyncCallback(loadbalanceCompleted);
AsyncOperation async = AsyncOperationManager.CreateOperation(null);
worker.BeginInvoke(LoadbalnceCallBack,async);
}
public void loadbalanceCompleted(IAsyncResult result)
{
loadbalancedelegate worker = (loadbalancedelegate) ((AsyncResult)result).AsyncDelegate;
AsyncOperation async = (AsyncOperation)result.AsyncState;
worker.EndInvoke(result);
}
delegate void setControlsBalanceDelegate(BalanceOB ball);
void setControlsBalance(BalanceOB ball)
{
if (this.InvokeRequired)
this.Invoke(new setControlsBalanceDelegate(this.setControlsBalance), new
object[] { ball });
else
{ //Update Data on Form (Windows App)
}
}
I would probably do the following:
In your timer code which runs every second, I would check if the internet connectivity is available by P/Invoke (which is faster way than having the service throw an exception, and looks like it would suit your cause as well). For some reference look here
I would have the P/invoke code also set a flag temporarily somewhere (make sure it is thread safe) and before making any web service calls, i would check if the flag is in a valid state for the client to make that call.

WCF: Self-host a NetTcp service, doesn't resolve

I am trying to host a WCF service, using NetTcpBinding in a Windows service. (I'm going to use it as an API for various clients both Web and Windows32) Obviously, I am doing this within a test host before putting it in a Windows service.
I have the following contract:
namespace yyy.xxx.Server.API.WCF
{
[ServiceContract]
public interface ISecureSessionBroker
{
[OperationContract]
string GetSessionToken(string username, string encryptedPassword, string clientApiKey, string clientAddress);
}
}
with the following implementation:
namespace yyy.xxx.Server.API.WCF
{
public class SecureSessionBroker : ISecureSessionBroker
{
#region ~ from ISecureSessionBroker ~
public string GetSessionToken(string username, string encryptedPassword, string clientApiKey, string clientAddress)
{
return Guid.NewGuid().ToString();
}
#endregion
}
}
I am hosting the WCF service using the code below (within a class/method):
try
{
_secureSessionBrokerHost = new ServiceHost(typeof(SecureSessionBroker));
NetTcpBinding netTcpBinding = new NetTcpBinding();
_secureSessionBrokerHost.AddServiceEndpoint(typeof(ISecureSessionBroker), netTcpBinding, "net.tcp://localhost:8080/secureSessionBrokerTcp");
int newLimit = _secureSessionBrokerHost.IncrementManualFlowControlLimit(100);
// Open the ServiceHost to start listening for messages.
_secureSessionBrokerHost.Open();
}
catch (Exception ex)
{
throw;
}
The key thing here is that I do not want to have to rely on an App.config file. Everything must be configured programmatically. When I run this code, the service appears to come "up" and listen. (ie. I have no exceptions)
BUT when I use the client code below:
string secureSessionBrokerUrl = string.Format("{0}/secureSessionBrokerTcp","net.tcp://localhost/8080",url);
EndpointAddress endpointAddress=new EndpointAddress(secureSessionBrokerUrl);
System.ServiceModel.Channels.Binding binding = new NetTcpBinding();
yyy.xxx.Windows.AdminTool.API.WCF.SecureSessions.SecureSessionBrokerClient
client = new yyy.xxx.Windows.AdminTool.API.WCF.SecureSessions.SecureSessionBrokerClient(binding,endpointAddress);
string sessionToken=client.GetSessionToken("", "", ""); // exception here
MessageBox.Show(sessionToken);
... I always get an exception. At the moment, I am getting:
This request operation sent to
net.tcp://localhost:8080/secureSessionBrokerTcp
did not receive a reply within the
configured timeout (00:01:00). The
time allotted to this operation may
have been a portion of a longer
timeout. This may be because the
service is still processing the
operation or because the service was
unable to send a reply message.
Please consider increasing the
operation timeout (by casting the
channel/proxy to IContextChannel and
setting the OperationTimeout property)
and ensure that the service is able to
connect to the client.
So I guess it cannot resolve the service.
Where am I going wrong? How do I test for the existence of the service over TCP? I have used the SvcTraceViewer and I just get the same message, so no news there.
I would prefer to ask the user for a URL of the service, so they would enter "net.tcp://localhost:8080" or something, which would then be used as a BaseAddress for the various calls to the SecureSessionBroker (and other) WCF services ... without resorting to App.config.
Unfortunately, all the examples I can find all use the App.config.
Interestingly, I can host the service using the VS Host and the client connects fine. (Using:
D:\dev2008\xxx\yyy.xxx.Server>WcfSvcHost.exe /service:bin/debug/yyy.
xxx.Server.dll /config:App.config)
Ok, it came to me in a flash of inspiration.
I was using a Windows Form (alarm bells) to "host" the service. Clicking out of the form, I used a bit of code to call the service (included) on a button click. Of course, the service was not in its own thread, so the service could not respond.
I've fixed it by putting the Service container (which contains the host) within its own thread:
Thread thread = new Thread(new ThreadStart(_serviceWrapper.Start));
thread.Start();
The Start() method sets up the ServiceHost.
I incorrectly thought that while a WCF Service Host will create threads for incoming requests, it will only do this if it is in its own non-blocking thread (ie. not a UI thread).
Hope it helps someone else.

Categories

Resources