My scenerio is like this:
On the server there is an application which exposes a COM object allowing to interact with this application programaticaly. However I can connect only once through COM due to licence restrictions. So, after initialization a COM object will return me a more specified ConnectionObject.
I need an advice what management model I schould chose for my service which will be interacting with the ConnectionObject:
Per-Call Service:
I have two options here:
I can log through COM, perform operation and Logout releasing the connection. But this logging process is somewhat time consuming.
I could create some sort of
singleton class which could keep
reference to the ConnectionObject.
The problem is that I do not know
how to share the same instance of
object through different instances
of the service? Is it possible?
Singleton Service:
The problem of sharing ConnectionObject does not exists. Object will be created at the begining of life of the service and freed when service will be shut down. However I've read that using this kind of service is not recommended.
Thanks for any advices.
Given your requirements with the COM object, and the time consuming log in and out process - I would go with the singleton service. We use our WCF services like this all the time (also talking to legagy COM objects).
You can add the following attribute to the class definition of your WCF service to get the behaviour:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyServiceContract
{
[OperationBehavior]
public void MyServiceCall ()
Related
I am developing an Service-Oriented based application for Hotel Reservation System using WCF architecture. It has following 3 three components:
1. WCF Service that has Service and Data contracts for invoking moudules of room reservation.
2. WCF Host that keeps log of service access by client
3. WCF client that has UI for Hotel Reservation.
I am looking for guidelines to implement concurrency in my application having following features:
1. Only one request shall be entertained at the time.
2. If more than one requests are received, then these should be synchronized using locks/mutex/semaphores.
Coding guidelines shall be helpful.
I think this is the allocation issue of the external resources, such as the database access, the I/O for on the single file. WCF supports transaction and transmitting it on the client-side. We are capable of locking the access to the database by using transaction when another client attempt to access it.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transactions-overview
Moreover, we can also use the shared lock which locks the service instance, occupying all the resource lest the other instance access the service, please refer to the below code.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple)]
class MyService : IMyContract
{
public void MyMethod()
{
lock(typeof(MyService))
{
...
MyResource.DoWork();
...
}
}
}
static class MyResource
{
public static void DoWork()
{
lock(typeof(MyService))
{
...
}
}
}
Please refer to the below link, Chaper8(concurrency management), resources and services, deadlock avoidance.
https://ashishmit99.files.wordpress.com/2013/01/oreilly-programming-wcf-services-3rd-edition-aug-2010.pdf
Here is an official document relates to Concurrency mode, aiming to solve access conflict from the multiple users.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/sessions-instancing-and-concurrency
For obscure reasons I need to connect to a service with .NET remoting from WITHIN the service itself.
To clarify:
there's a client application connecting to the service:
IEngine engine = (IEngine)Activator.GetObject(typeof(IEngine), "tcp://169.18.1.100:1966/Engine");
When a certain call is made to the service it loads an AppDomain with a plugin dll which computes something. But now this dll needs to call functions from the service its embedded in and it cant call them directly since it lives in its own AppDomain.
So can I just call this from within the AppDomain?
IEngine engine = (IEngine)Activator.GetObject(typeof(IEngine), "tcp://localhost:1966/Engine");
The object is published with:
RemotingServices.Marshal(this, engineUri);
It does work for single calls at least, but maybe there's threading and release of the IEngine or other issues to consider?
I hope its clear.
If you store the instance of IEngine that was passed to RemotingServices.Marshal then you wouldn't need to call Activator.GetObject from within the service itself as it will be the same instance used by client applications. It will probably need some re-structuring but it would save any calls to IEngine from within your service going over the network stack:
IEngine this.engine = new Engine();
RemotingServices.Marshal(this.engine, engineUri);
// this.engine will be the same instance used by client applications and can also be passed around within your service.
for a third party application I need to program a Com Server. This is no problem but I need the COM Server to run only in one instance. This instance should run as a service so that it is not created every time new.
The COM Application is created by vbs every time new.
Dim myCom
Set myCom = Nothing
Set myCom = CreateObject("MyCom.Application")
myCom.DoAction
The Com Server itself creates a database connection and I want to connect once and not for every creation.
I hope you understand what I mean. If not contact me pleade via comment. Thanks.
Chris
Take a look at ExeCOMServer:
ExeCOMServer encapsulates the skeleton of an out-of-process COM server in
C#. The class implements the singleton design pattern and it's thread-safe.
To start the server, call CSExeCOMServer.Instance.Run(). If the server is
running, the function returns directly.
This is about my solution to that question
It is been a long time since my last c# coding, and it is my first time to write a Web Service...
Previous Question:
I need to use a DLL on an Ubuntu with Python. Final solution is using a web service for that propose...
My problem is, the API is used for a kind of payment. There are three basic function of the DLL to be used in the webservice... First one is used for connection to the server, second one is asking available payments, third one is selecting one and making the payment...
Since my system is using Python, I wish to keep the logic that selects the payment method on python, not on the web service.
And my problem is, when I make a connection, webservice must create a connection object, and do the following two steps using that connection. That it may dispose that connection object and create a new one for the next connection and payment.
So, my Python code will do something like that...
Use web service and create a connection
Get a list of available payments from web service (these two functions can be used as a single function in the web service)
Do some calculation and select the proper payment in python...
Send payment method info to web service...
All these steps must be done with the connection object from the first step.
As I said before, I do not have much knowledge about web services and using them on python... So I'm confused whether I may use the same connection object for steps 2 and 4. If I create the connection object as a global in my web service on the connection step, then my following function calls use that object? In OOP that's the way it must be, but I can not be sure if it will be same in web services?
Some code snippet :
namespace paymentType{
public class x : System.Web.Services.WebService{
ConnectionObj conn;
ConnResult result;
[WebMethod]
public void ConnectToServer(String deviceId){
conn = new ConnectionObj();
result = baglanti.Connect(deviceId);
}
[WebMethod]
public List<int> GetCompanyList(){
List<int> kurumlar = new List<int>();
if (sonuc.CRCStatus){
if (baglanti.CompanyList != null) { blah blah blah...}
Since conn is a global, can i set it in the function call ConnectToServer and use the baglanti object for the other functions...
UPDATE: Let me try to get it more clear...
When I connect to remote server (via function in the DLL), remote server accepts my connection and give me a somewhat unique id for that connection. Then I ask for available payments for a customer. Server sends all available ones with a transaction id belong to that transaction. And in the final step, I use the transaction id that I want for doing the payment. Problem is, each transaction id is usable within the connection that it was created. So, I must request for transaction id and confirm the one I want in the same connection...
But as far as I see, best solution is using a single function call and do all the job on the web service since API provider considers removing the connection-transactionId lock might cause some security vulnerabilities...
But on the other hand, I do not want to handle it on the web service...
One more question... On the connection step, creating the connection and using set/get functions or returning the connection object and pass it back to the web service for each following step might work?
If you're communicating using a web service, it should preferrably be stateless – that is, you should always send any context information the service implementation needs in the request. While technologies that let you implement stateful web services exist, they'd likely make things more complicated, not less.
I'm not clear from your description on why you need the connection object to be created in Step 1, or why you can't just create a different connection object for steps 2 and 4 – which is how I'd implement this.
My project was standalone application then I decided to split it as client & server because I need powerful CPU usage and portability at the same time. Now multiple clients can connect to one server.
It was easy when 1 by 1 processing did the job. Now I need to call the same function & scope area again & again at the same time -via client requests-
Please can anyone give me some clue how should I handle these operations, I need to know how can I isolate clients' processes from each other at the server side? My communication is asynchronous, server receives a request and starts a new thread. I think I pass a parameter which one carries the client information, and another parameter as job id -to help client back, client may ask for multiple jobs and some jobs finish quicker than others-
Should I instantiate the class Process on each call? Can I use a static method, etc, any explanation will be of great help!
Below is the part of my code to need modification
class static readonly Data
{
public variable listOfValues[]
}
class Process
{
local variable bestValue
function findBestValue(from, to)
{
...
if(processResult > bestValue) bestValue = processResult
...
}
...
for(i=0;i<10;i++) startThread(findBestValue(i*1000,i*1000+999));
...
}
EDIT: I think I have to instantiate a
new Process class and call the
function for each client and ignore
the same client for same job since job is already running.
Not getting into your application design, since you didn't talk much about it, I think that your problem is ideal for using WCF WebServices. You get client isolation by design because every request will start in it's own thread. You can create WCF host as standalone application/windows service.
You can wrap your communication with WCF service and configure it to be PerCall service (meaning each request will be processed separately from others).
So you'll clean up your buisness logic from syncronization stuff. That's the best way, because managing and creating threads is not difficult to implement, but it is difficult to implement correctly and optimized for resources consumption.