Benötige speziellen Timer...
-
Hallo Codefinder,
Ja, die Timerqueue-Timer werden in einem separaten Thread ausgeführt. Wenn das absolut nicht sein darf, dann könntest du mit User Mode APCs arbeiten oder dafür ein eigenes Scheduling implementieren. Vielleicht kannst du mit der Windows Fiber-API etwas anfangen?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/using_fibers.asp
Grundsätzlich ist jedes Problem unter Windows lösbar. Vielleicht muß man aber manchmal ein paar Einschränkungen in Kauf nehmen.

-
N' Abend,
Also, Ähm, danke aber:
.MSDN schrieb:
Asynchronous Procedure Calls
An asynchronous procedure call (APC) is a function that executes asynchronously in the context of a particular thread. When an APC is queued to a thread, the system issues a software interrupt. The next time the thread is scheduled, it will run the APC function. An APC generated by the system is called a kernel-mode APC. An APC generated by an application is called a user-mode APC. A thread must be in an alertable state to run a user-mode APC.
Also ich hab doch eigentlich eingangs gesagt (bzw. sogar unterstrichen) was die Rahmenbedingungen sind, oder?
KEINE THREADS!
und damit sind auch irgendwelche Synchronisationsmethoden (Fiber-API) hinfällig...Andromeda schrieb:
Grundsätzlich ist jedes Problem unter Windows lösbar.
Mit so nem Satz wär ich vorsichtig ^^.
Hm naja trotzdem danke, an alle... . Hab das doch mit nem Dummy-Fenster gemacht. Funktioniert auch soweit, wenns auch ein bissl dirty ist...
PS: Bin heute sowieso etwas angesäuert...nehmt meine teilweise etwas aggressiv formulierten Antworten nicht zu ernst
.
-
Hallo,
CodeFinder schrieb:
KEINE THREADS!
und damit sind auch irgendwelche Synchronisationsmethoden (Fiber-API) hinfällig...Wenn du Fibers benutzt, werden keine zusätzlichen Threads gestartet. Alle von dir erzeugten Fibers laufen in einem einzigen Thread, das heißt, du must dich dabei nicht mit Threadsynchronisation auseinandersetzen. Dafür mußt du aber die Umschaltung selbst in die Hand nehmen. Vielleicht kennst du das Konzept von Coroutines? Im Prinzip sind Fibers nichts anderes.

-
CodeFinder schrieb:
KEINE THREADS!
und damit sind auch irgendwelche Synchronisationsmethoden (Fiber-API) hinfällig...Wie Andromeda auch schreibt... Fibers laufen i.d.R. in *einem* Thread ab. Für das Scheduling musst Du aber selber sorgen!
Hab hier ein grosses System mit Fibers laufen! Super Sache! Musst dich nicht mit Snychronisationsproblemen rumärgern, weil es sowas nicht gibt!
-
Hm jo kennsch, aber so läuft das jetzt und das bleibt deswegen jetzt so. Ne komplette Umschaltung zu implentieren lohnt den Aufwand nicht
. Aber thX!EDIT, @Jochen:
Wie lang ist der ('Umschalt-')Code ?^^
-
CodeFinder schrieb:
Wie lang ist der ('Umschalt-')Code ?^^
Kannst selber Debugger
(SwitchToFiber) sind aber ca. 20-30 Assembler-Befehle; und benötigt *kein* Switch in den Kernel!!! Reines User-Mode Scheduling.PS: Der aktuelle SQL-Server 2005 verwendet intern Fibers um auf maximale Performance zu kommen! Nur durch die minimale Umschaltzeit lässt sich maximaler Durchsatz erzielen

-
Hm k, aber ich kann recht wenig, naja, sehr wenig
, Assembler... Glaub der Aufwand lohnt da nicht :p . Aber ok es wär ne Idee gewesen
.
-
Klar hab ich die Fragestellung gelesen. Anfangs kam "keine Threads", bloss dann kam das:
CodeFinder schrieb:
PS: Hab mir den Artikel noch nicht komplett durchgelesen, da mir zwischenzeitlich ein etwas andere Idee kam (auf die in dem Artikel, wenn ich das richtig überflogen habe, auch später drauf angesprochen wird): Man kann sich seinen Timer ja auch selbst schreiben .
Meine (bisherige) Idee ist folgende:
Ich erstelle einen Thread in dem einfach die entsprechende (vorher festgelegt) Periode gezählt wird. Anschließend wird die Callback-Funktion aufgerufen, in der die periodisch wiederkehrenden Anweisungen gekapselt sind. Das ganze kann man dann noch in eine Klasse legen (, was glaube ich auch in dem Artikel gemacht wird) . In dem Thread muss dann natürlich auf eine Abbruchvariable kontrolliert werden, ob man den entsprechenen Timer nicht gerne beendet haben möchte.hustbaer schrieb:
denn genau das kannst du mit timer-queue timern fix und fertig vom System haben
Ich meinte: was auch immer der 2. Thread von dem du schreibst machen soll wenn die Zeit rum ist kannst du auch in der Callback Funktion machen die du bei einem timer-queue Timer hast. Klar jetzt was ich meinte?

CodeFinder schrieb:
Also beim Hauptthread wird NICHT beblocked und die Bearbeitung, also die Callback-Funktion, ist auch kein neuer Thread
Ok, ohne irgendwelche weitere Dinge die wir vom Hauptthread verlangen können ist das *unmöglich*, denn es gibt keinen Punkt wo wir (bzw. "der Timer") uns einklingen können ("kann").
Wenn der Hauptthread per Definitionem nen Message-Pump macht, dann kannst du das selbe verwenden wie COM es auch macht um mit STA Apartments zu kommunizieren. Lustigerweise ist das genau das was du ursprünglich angedacht hast. Unsauber finde ich es auch, aber wenn die COM Implementierung von MS selbst es so macht wird es wohl die beste Lösung sein:MSDN schrieb:
Dispatching calls to an STA is more complex, simply because no other threads can enter an existing STA. Unfortunately, when ORPC requests arrive from off-host clients, they are dispatched using threads from the RPC thread cache, which by definition cannot execute in the object’s STA. To enter the STA and dispatch the call to the STA’s thread, the RPC thread uses the PostMessage API function to enqueue a message onto the STA thread’s MSG queue as shown in Figure 5.5. This queue is the same FIFO queue used by the windowing system. This means that to finish dispatching the call, the STA thread must service the queue via some variation on the following code:
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
This code implies that the STA thread has at least one window that can receive messages. When a thread enters a new STA by calling CoInitializeEx, COM creates a new invisible window by calling CreateWindowEx. This window is associated with a COM-registered window class whose WndProc looks for a predefined window message and services the corresponding ORPC request by calling the IRpcStubBuffer::Invoke method on the interface stub. Note that because windows, like STA-based objects, have thread affinity, the WndProc will execute in the apartment of the object.Der Artikel heisst übrigens "Standard Marshaling Architecture" falls du selbst weiteres nachlesen willst - und sollte auch mit nem Stück aus dem Text leicht in der MSDN zu finden sein.
Wenn dir ein Fenster pro Objekt zu viel ist kannst du es ala COM machen und ein Fenster für alle Objekte verwenden, du kannst dann ja Parameter als WPARAM/LPARAM mitgeben (bzw. wenn nötig nen Pointer auf was grösseres).
---
Mich hat das ehrlich gesagt leicht überrascht, da ich dachte Windows hätte schon für interne Zwecke eine Message ID über die man gleich in DispatchMessage ne Callback Funktion aufrufen lassen kann ohne dass erst irgendeine WindowProc oder sonstwas aufgerufen werden muss -- was ja der einfachere Weg wäre.
p.S.: die wohl einfachere Version (wenn's für dich ausreichend ist und funktioniert) wäre wohl SetTimer mit hWnd == 0 zu verwenden, und als Zeiger auf die Daten dann nIDEvent zu verwenden -- in der Callback Funktion solltest du den selben Wert dann wieder mitbekommen. Zumindest interpretiere ich die Doku so -- ist nicht 100% klar geschrieben für mich.
Allerdings weiss ich nicht was passiert wenn das Programm in dem dein Code dann läuft zufällig den selben Wert für nIDEvent ebenfalls mit hWnd == 0 verwendet...

p.S.: sorry dass es so lange geworden ist, aber ich hoffe es hilft diesmal ein wenig

-
Erstmal (nochmal) thX @hustbaer!!
Ich hab mich in meiner Beschreibung etwas falsch ausgedrückt...
"Anschließend wird die Callback-Funktion aufgerufen, in der die periodisch wiederkehrenden Anweisungen gekapselt sind."
Das ist natürlich schwachsinn... . Man müsste dann dem Hauptprogrammthread ne Nachricht senden, wo dann die Funktion aufgerufen wird. So würde die Funktion ja aus dem Thread aufgerufen und folglich auch darin ausgeführt - Das will ich ja verhindern - . Ich hatte mir das so auch gedacht, nur nicht so geschrieben
.-Sry-Werd's jetzt provisorisch mit nem Dummy-Fenster machen (da das jetzt gerade endlich mal funktioniert ^^).
Das sieht aber auch interessant aus (wobei es ja vorraussetzt das UINT immer 32Bit ist, was ja i.d.R. der Fall ist):
hustbaer schrieb:
p.S.: die wohl einfachere Version (wenn's für dich ausreichend ist und funktioniert) wäre wohl SetTimer mit hWnd == 0 zu verwenden, und als Zeiger auf die Daten dann nIDEvent zu verwenden -- in der Callback Funktion solltest du den selben Wert dann wieder mitbekommen. Zumindest interpretiere ich die Doku so -- ist nicht 100% klar geschrieben für mich.
Ich werd mal gucken, ob ich das noch umbastle, auf jeden Fall: Danke an alle!
-
Also mein MSDN sagt mir dass nIDEvent ein UINT_PTR ist, also ein unsigned integer wo immer min. gleich gross wie ein Pointer ist. Von daher kein Problem.