C# Windows Service, threads?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Montaner
  • Registratie: Januari 2005
  • Laatst online: 04-07 12:21
Ik heb een kleine service geschreven om XML berichtjes te transformeren met XSL en deze daarna uit te laten printen. Maar ik krijg deze melding: The calling thread cannot access this object because a different thread owns it.

Voor het checken van de bestanden gebruik ik een timer, die start in de OnStart:
C#:
1
2
3
4
5
6
7
8
                if (findPrinter() > 0)
                {
                    System.Timers.Timer printNetterCheck = new System.Timers.Timer();
                    printNetterCheck.Elapsed += new ElapsedEventHandler(OnTimedEvent);

                    printNetterCheck.Interval = 30000;
                    printNetterCheck.Enabled = true;
                }


De timed event:
C#:
1
2
3
4
        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {            
            getFiles();
        }


Mochten er bestanden gevonden worden, in de getFiles, wordt de print opdracht aangeroepen:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
                foreach (string file in files)
                {
                    try
                    {
                        StringWriter xslTransformResult = new StringWriter();
                        XslCompiledTransform xslt = new XslCompiledTransform();
                        xslt.Load(xslPath);
                        xslt.Transform(file, null, xslTransformResult);

                        if (print(xslTransformResult) == 1)
                        {
                                  //functie gebeuren


De print functie:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
        private int print(StringWriter transformedXML)
        {
            //assume OK
            int rc = 1;

            try
            {
                StringReader printNetterStreamReader = new StringReader(transformedXML.ToString());
                PrintSystemJobInfo printNetterJob = printer.AddJob("PrintNetterPrint");

                Stream printNetterStream = printNetterJob.JobStream;


                Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());

                printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
                printNetterStream.Close();
            }
            catch (Exception e)
            {
                //return fail
                rc = -1;
                eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
            }

            return rc;

        }


Bij het aanroepen van de print krijg ik dus bovenstaande melding.

Ik heb al een hoop gevonden over een Dispatcher etc, maar die bestaat niet bij een service.

Acties:
  • 0 Henk 'm!

  • TallManNL
  • Registratie: Oktober 2005
  • Laatst online: 07-07 21:20
de printer variabele in je print functie, wordt die door je findPrinter() functie in de Service start gevuld?

Je timer event wordt op een andere thread afgevuurd als waarop je Onstart is gedraait.

Ik zou eens kijken of het vullen van je printer variabele ook in je print functie gebracht kan worden.

geheelonthouder met geheugenverlies


Acties:
  • 0 Henk 'm!

  • Montaner
  • Registratie: Januari 2005
  • Laatst online: 04-07 12:21
Het gaat fout op de volgende regel:

C#:
1
PrintSystemJobInfo printNetterJob = printer.AddJob("PrintNetterPrint"); 
TallManNL schreef op maandag 22 april 2013 @ 14:08:
de printer variabele in je print functie, wordt die door je findPrinter() functie in de Service start gevuld?

Je timer event wordt op een andere thread afgevuurd als waarop je Onstart is gedraait.

Ik zou eens kijken of het vullen van je printer variabele ook in je print functie gebracht kan worden.
Ah, ik begrijp nu wat je bedoelt.. ik ga het eens proberen om te printer pas te zoeken als de eerst keer de file check gedaan wordt, en dus vanuit de timer job.

[ Voor 69% gewijzigd door Montaner op 22-04-2013 15:09 ]


Acties:
  • 0 Henk 'm!

  • Roet
  • Registratie: Augustus 2001
  • Laatst online: 16:32
Wat mogelijk helpt, is even checken op InvokeRequired. Als dat true is kan je proberen de print methode aan te roepen met een BeginInvoke zodat deze in de juiste thread wordt aangeroepen?

Watje uiteraard ook kan doen is het probleem voorkomen door de printer variabele in de methode te vullen in plaats van bij de OnStart (andere thread), zoals TallManNL opmerkt.

[ Voor 16% gewijzigd door Roet op 22-04-2013 15:15 ]


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Afhankelijk van de complexiteit kan je misschien ook je printer naar een dedicated thread halen, en dan je uitvoer laten posten naar een queue oid. je kan dan ook nog je files in parallele threads transformen.

of als je load vrij klein is, gooi die timer-zooi weg en doe een while(true) { doe_werk; Thread.Sleep(30 * 1000); } (desnoods in een dedicated thread als je ook nog een UI hebt lopen).

-niks-


Acties:
  • 0 Henk 'm!

  • __fred__
  • Registratie: November 2001
  • Laatst online: 05-07 01:00
Let op. Je timer event draait elke keer op een andere thread, dat betekent dus ook dat je events re-entrant zijn. Als je functie langer dan 30 seconden draait, dan gaan ze elkaar in het vaarwater zitten. Voor dat je het weet print je bestanden dubbel of geef je delete instructies voor bestanden die al weg zijn.

Daarnaast creeer je kennelijk het printer object (PrintQueue w.s.) in je service thread, en daarna roep je hem aan op de timer thread. Die vindt dat niet leuk.

Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Je kunt ook zonder Timer via een FileSystemWatcher.

"The shell stopped unexpectedly and Explorer.exe was restarted."

Pagina: 1