CLMFT

I am trying to open and run DSS node from another application, in this case NI's LabVIEW. Using the first Hosting tutorial as a guide.I created a new class which executes DssEnvironment.from within its constructor. I also created a method for my class, DSSShutdown, which executes DssEnvironment.Shutdown and DssEnvironment.WaitForShutdown, so the node didn't time out. From within LabVIEW, I can successfully create an instance of the class which opens a DSS node. I can then invoke my DSSShutdown method, which seemingly does its job (I can no longer access the node via IE). My issue is if I try to run thr sequence agian, I get an exception about not being able to create a TCP Listener. If I close LabVIEW and then start it again, I can then get it to work again, but only once. Then I get the same exception again. Is there any reason why this would be occuring Furthermore, is there anyway I can be sure the listeners are properly disposed of


Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

Paul C Roberts

Hi,

Currently, DssEnvironment can only be run once within any given AppDomain. The exception that you are seeing is a result of this. If you need to run DssEnvironment multiple times within the lifetime of a process, then you will need to run each instance inside of a new appdomain.

Hope this Helps

Paul





Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

CLMFT

How do you use DSSEnvironment ina different AppDomain




Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

CLMFT

I'm not at all sure that I'm doingthis right, so if someone could post or direct me to a brief how-to it would be great, but I think I managed to create a new AppDomain and intialize DSSEnviornment. However, when I run the code the second time, I now get an exception statinhg "Create can only be called once per AppDomain".




Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

Andreas Ulbrich

Make sure to create a new appdomain the second time you want to initialize DssEnvironment.

Here is how I would go about it:

1) Create a class that allows you to marshal through domain boundaries.

public class DssCrossDomainHelper : MarshalByRefObject

{

public void Initialize(...)

{

DssEnvironment.Initialize(...);

}

public void Shutdown()

{

DssEnvironment.Shutdown();

}

// add here what you want to do Dss

public void DoStuff(...)

{

// do whatever you want to do here
}

}

2) You can now use DSS like this

AppDomain domain = AppDomain.CreateDomain("DSS", AppDomain.CurrentDomain.Evidence);

DssCrossDomainHelper dss = (DssCrossDomainHelper)(domain.CreateInstance(

typeof(DssCrossDomainHelper).Assembly.FullName,

typeof(DssCrossDomainHelper).FullName).Unwrap());

dss.Initialize(...);

dss.DoStuff(...)

dss.Shutdown();

dss = null;


AppDomain.Unload(domain);

3) If you want to initialize DSS again you have to do ALL of 2) again, i.e. make sure that you create a new domain.

Hope this helps,

Andreas






Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

CLMFT

The code I was using is very similar to what you posted, but it still is not working. Here is what I have:


public class CommLink : IRoboticsComm
{
private LogOutput log;
private AppDomain clDomain;
private CommLinkDSS dssNode;

public CommLink()
{
try
{
StartLogForm();

// Create new AppDomain
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationBase = @"C:\Microsoft Robotics Studio (1.5)\bin\";

clDomain = AppDomain.CreateDomain("CommLinkDomain", null, domainSetup);

dssNode = (CommLinkDSS)(clDomain.CreateInstance(
typeof(CommLinkDSS).Assembly.FullName,
typeof(CommLinkDSS).FullName).Unwrap());

string result = dssNode.InitializeDSSNode();
Log(result);
}
catch (Exception e)
{
Log("Failed: " + e.Message);
}
}
public void StopDSSNode()
{
dssNode.StopDSSNode();
dssNode = null;
AppDomain.Unload(clDomain);
Log("Shutting Down");
}

private void StartLogForm()
{
log = new LogOutput();
log.Show();
}

private void Log(string str)
{
log.txtOutput.Text += str + "\r\n";
}
}


public class CommLinkDSS : MarshalByRefObject, IRoboticsComm
{
public string InitializeDSSNode()
{
string error;
try
{
DssEnvironment.Initialize(50000, 50001);
error = "DSS Node Initialized.";
}
catch (Exception e1)
{
// Try it again with different ports to raise AppDomain exception
try
{
DssEnvironment.Initialize(50000, 50001);
error = "DSS Node Initialized.";
}
catch (Exception e2)
{
error = e2.Message;
}
}
return error;
}

public void StopDSSNode()
{
DssEnvironment.Shutdown();
DssEnvironment.WaitForShutdown();
}


To explain how everything is being used, I'm using .NET functionality in the application LabVIEW to create an instance of CommLink. LabVIEW then waits for an action by the user before calling the StopDSSNode method on CommLink and disposing of its reference to it. Then these actions are repeated, LabVIEW creates a new CommLink instance, etc etc. Unfortunatly, the second time around I still get the exception about "Create can only be called once per AppDomain."






Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

CLMFT

Thinking this may be an issue with LabVIEW, I also posted my problems to one of the NI forums. This was a response I got:

From Jonathan N @ NI Discussion Forums:

I just wanted to add in a little extra detail to the post. The main issue for LabVIEW is that we do not spawn off another process when running VIs. By that I mean the VI is run within the same process as the IDE itself, LabVIEW.exe. This is different than other IDEs, such as Visual Studio. Visual Studio for example creates a new process to run the executable you created. In Visual Studio's case, the .NET assembly is loaded into that new process. In LabVIEW's case, the .NET assembly is loaded into the LabVIEW process.

Because of this nature, this impacts on what can and can't be released. As of LabVIEW 8.5 and earlier, once you load a .NET assembly into memory, the assembly is locked into memory and you must restart LabVIEW to release that component.

I'm not sure if this has anything to do with the problem I'm having, but I thought I'd share the information in case it does.






Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

George Chrysanthakopoulos

indeed, at this point i dont see anything wrong with your code and we know DssEnvironment supports multiple app domains per CLR process (as long as different TCP and HTTP ports are used).





Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

Abosho

Anything new about that

I am dealing with the same AppDomain problem at the second initialization.

How could I turn on / off a service from within a winforms app

Thanks,

Ariel





Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

George Chrysanthakopoulos

services can be dropped be issuing a Drop message to them.The hosting tutorials show how to send messages from a host to a service, and Drop is a regular message.

The problem you are having is not being able to start second DssHost, in a second appdomain, with different ports





Re: Microsoft Robotics - Decentralized Software Services (DSS) Issue with Listeners

Abosho

Thanks George,

I'll describe my scenario:

I'am using the Webcam Service to expose my webcam via http. I wrote a simple winforms program than "starts" and "stops" the webcam hosting, wich uses always the same port.

1- Initialize with port 50000

2- Shutdown

3- Initialize with port 50000 again...

Based on the Andreas Ulbrich's post, I create a new appdomain to initialize the service for the second time. Unfortunately, I still get the same error when calling DssEnvironment.Initialize ----> "Create can only be called once per AppDomain"

Ariel