Avatar billede Droa Seniormester
30. juni 2014 - 13:53 Der er 15 kommentarer og
1 løsning

Hente data fra wcf singleton objectet

Så jeg sidder for første gang og læser op omkring wcf, da jeg har hørt det skulle være et godt interface til kommunikation med en Windows Service, fra en Desktop application.

Jeg har dog lagt mærke til nogen lidt underlige ting.

det wcf hosted object skal være et singleton, da jeg går ud fra det gør det mere tråd-sikkert.

Men hvordan kan jeg så indhente data fra Selve servicen?

Jeg har en datatabel som bliver vedligeholdt af en af servicens tråde, som henter informationerne fra log-læsninger.

også selve WCF hostingen ser sådan her ud.


using (ServiceHost host = new ServiceHost(new PersonService(), new Uri[] { new Uri("http://localhost:8010") }))
                {
                    host.AddServiceEndpoint(typeof(IPersonService), new BasicHttpBinding(), "Person");
                    var endpoint = host.AddServiceEndpoint(typeof(IPersonService), new WebHttpBinding(), "xml/Person");
                    endpoint.EndpointBehaviors.Add(new WebHttpBehavior());

                    ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
                    sdb.HttpHelpPageEnabled = false;

                    host.Open();

                    Console.WriteLine("Service is available. " +
                      "Press <ENTER> to exit.");
                    Console.ReadLine();

                    host.Close();
                }


Hvad for taktikker findes der til og arbejde med objekter der aktivt bruges af andre tråde, til wcf-hosting?
Avatar billede arne_v Ekspert
30. juni 2014 - 15:28 #1
Jeg tror at det du spoerger om er:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class PersonService:IPersonService
{
Avatar billede arne_v Ekspert
30. juni 2014 - 15:30 #2
Men naar det er sagt, saa er jeg meget skeptisk overfor om du er paa rette spor.

Singleton goer det ikke traad sikker - singleton goer det traad usikkert.

Hvis du vil bruge HTTP som transport hvorfor saa ikke hoste i ASP.NET?

Jeg tror ikke at Console virker i en Windows service.
Avatar billede montago Praktikant
30. juni 2014 - 16:51 #3
Arne:

det ligner lidt en Self-hosted WCF Service - som startes i en Console App..
Avatar billede arne_v Ekspert
30. juni 2014 - 17:59 #4
Hvis det er en console app og ikke en windows service, saa virker Console naturligvis fint.
Avatar billede montago Praktikant
30. juni 2014 - 23:06 #5
tror ikke du forstår:

det er en Console APP som hoster en WCF Service..
Avatar billede Droa Seniormester
01. juli 2014 - 00:57 #6
måske var jeg ikke grundig nok i mit spørgsmål :)

det er ikke selve servicen der ses kode på, da selve servicen er lidt over 50.000 linier kode, og er projekt jeg har arbejdet på i 2 år, så ville nok ikke engang give mig lov at vise alt koden på eksperten :)

det jeg spørger om at hvordan man bruger data på kryds af en wcf forespørgsel.

Jeg har leget lidt med det, jeg har haft nogen ideer...

hvis jeg nu f.eks har en del af min  PersonService der ser sådan her ud.

(hånd skrevet så nok ikke 100% korrekt)

[ServiceContract]
class PersonService
{
  int i = 0;
  [OperationContract]
  [WebGet]
  public int Adder(){
  i++;
  return i;
}
}


så vil en sinleton jo altid udskrive 1, da den opretter et nyt opbjekt hver gang.


den anden mulighed jeg har prøvet, er at gemme mine data direkte på en Static class


clas Program
{
public static int i = 0;
}


så jeg kan hente den med.


[ServiceContract]
class PersonService
{
  [OperationContract]
  [WebGet]
  public int Adder(){
  Program.i++;
  return Program.i;
}
}



det er den eneste løsning jeg selv er kommet op med, og det ser ikke kun meget dumt ud, men os uroligt usikkert...

så mit spørgsmål er om der ikke findes en bedre måde at hente data ind i mit wcf?

som sagt så er serviceen en ret stor service, der køre med omkring 50-60% cpu kraft konstant for at scanne lidt over 40-120.000 linier i sekundet, hvor den derefter skal lave en livestatus på dem igennem wcf.
Avatar billede arne_v Ekspert
01. juli 2014 - 04:19 #7
@#5

Muligt, men der staar windows service i spoergsmaalet.
Avatar billede arne_v Ekspert
01. juli 2014 - 04:20 #8
@#6

Har du prevet forslaget i #1?
Avatar billede Droa Seniormester
01. juli 2014 - 05:11 #9
jeg har heletiden brugt ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] i min service classe, da jeg køre det som object, det har dog intet og gøre med mit spørgsmål?
Avatar billede montago Praktikant
01. juli 2014 - 07:41 #10
Hvis alle dine WCF brugere skal deles om et object, skal du holde det i live - evt. ved at bruge det i en tråd.

Når det så er sagt, så er måden man gør et object trådsikkert ved:

- at bruge VOLATILE keyword på variable som skal accesses
- at bruge LOCK når man laver transaktions-lignende handlinger

Jeg har selv brugt STATIC til rod elementet:

class WCFService
{
  private static MyType SharedObj {get;set;}

  ctor ()
  {
      if(SharedObj == null) SharedObj = new... ;
  }
}
Avatar billede Droa Seniormester
01. juli 2014 - 08:58 #11
mange tak montago, det er noget i den stil jeg har leget lidt med, jeg havde dog ikke tænkt på at have en static i selve service objektet, men hvis det virker, så virker det jo:)

men hvordan har lock det med at have lidt over 500.000-800.000 skrivninger i sekundet, fra 10-12 forskellige tråede, mens den os skal snakke med wcf?
Avatar billede montago Praktikant
01. juli 2014 - 09:23 #12
Jeg ville nok lave en QUEUE<writeobj> som kunne tage imod dine skrivninger, som så i en tråd bulk indsætter hvad den nu skal indsætte.

QUEUE er ikke i sig selv threadsafe - men der findes versioner på nettet som er: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

at lave 800.000 locks i sekundet kan ikke lade sig gøre på små maskiner :) da det er MEGET tungt.
Avatar billede montago Praktikant
01. juli 2014 - 09:32 #13
tjek de her .NET collections ud: http://msdn.microsoft.com/en-us/library/system.collections.concurrent(v=vs.110).aspx
Avatar billede Droa Seniormester
01. juli 2014 - 09:34 #14
okay mange tak, men det ligner noget jeg kan bruge :)
Avatar billede montago Praktikant
01. juli 2014 - 09:55 #15
som sagt, skal man passe lidt på med LOCK...

dét man laver inde i en LOCK skal helst være tungere end at lave en LOCK

så fx:

lock(obj)
{
    antal++;
}

er måske overkill :)
og man skal passe på med at lave locks alt for mange steder.

Det er også en god ide at bruge 1 global objekt instans til at lave din LOCK med. (alt efter hvordan dit design er).. du vil jo gerne undgå DEADLOCK :)

allerhelst skal man designe sin arkitektur med henblik på at UNDGÅ at bruge LOCK, da det låser dit program -- ofte unødigt.

Hvis det er SQL ressourcer som du skal LOCK, kan det være du kan løse problemet ved at låse på SQL niveau: TABLE, ROW, CELL (jeg mener kun SQL kan lock på table og row niveau)
Avatar billede Droa Seniormester
17. december 2014 - 23:20 #16
nogen der stadig ville have point?
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester