Discussion:
Hintergrund-Verarbeitung
(zu alt für eine Antwort)
Manfred Berger
2011-07-21 14:29:11 UTC
Permalink
Hallo

Ich habe ein Makro, das nacheinander einzelne Zeichen auf den
Bildschirm schreibt. Zwischen den Zeichen gibt es unterschiedlich
lange zeitliche Verzögerungen, die ich mit Hilfe des Timers erzeuge.

Wenn diese Verzögerungen eine bestimmte Grenze (Größenordnung 5 sec)
überschreiten, werden die folgenden Zeichen zwar noch geschrieben,
werden aber erst sichtbar, wenn ein Stop durch eine Inputbox erfolgt.
Word arbeitet also im Hintergrund weiter.

Früher konnte man dies durch
Application.ScreenUpdating=False (bzw. True)
steuern. Diese Anweisung funktioniert aber nicht mehr.

Woher kommt dieser Effekt?
Kann man ihn ausschalten?
Kann man zumindest die Zeitgrenze ändern?

Servus
Manfred
Wolfram Jahn
2011-07-21 21:43:13 UTC
Permalink
Post by Manfred Berger
Kann man ihn ausschalten?
Wild geraten: hast Du mal DoEvents probiert nach dem Buchstabenschreiben?


Wolfram
Manfred Berger
2011-07-22 04:36:34 UTC
Permalink
Hallo Wolfram
Post by Wolfram Jahn
Wild geraten: hast Du mal DoEvents probiert nach dem Buchstabenschreiben?
Ich habe eher angenommen, daß es das Gegenteil bewirkt, aber es
funktioniert, wenigstens bei den ersten zaghaften Versuchen. Wir
werden weiter sehen.

Vielen Dank.

Servus
Manfred
Manfred Berger
2011-07-22 17:35:01 UTC
Permalink
Hallo Wolfram

Es funktioniert zwar, aber nur bedingt, denn

jeweils 4 Zeilen nach Beginn einer neuen Seite und nochmal in der
Mitte einer Seite legt es 3 Mal eine Pause ein, die mit zunehmender
Dauer des Programms immer länger wird.

Servus
Manfred
Wolfram Jahn
2011-07-22 21:37:23 UTC
Permalink
Post by Manfred Berger
Es funktioniert zwar, aber nur bedingt, denn
jeweils 4 Zeilen nach Beginn einer neuen Seite und nochmal in der
Mitte einer Seite legt es 3 Mal eine Pause ein, die mit zunehmender
Dauer des Programms immer länger wird.
Hm, schade.

Um jetzt noch weiter helfen zu können, müsste ich es mindestens
nachstellen, dazu reichen mir aber die Informationen nicht.

Falls Du ein Stück hinreichend neutralisierten Code bereit stellen
kannst, würde ich es glatt mal versuchen.

Allerdings habe ich 'nur' Word 2007.


Wolfram
Winfried Sonntag [MVP]
2011-07-22 20:10:26 UTC
Permalink
Post by Manfred Berger
Ich habe ein Makro, das nacheinander einzelne Zeichen auf den
Bildschirm schreibt. Zwischen den Zeichen gibt es unterschiedlich
lange zeitliche Verzögerungen, die ich mit Hilfe des Timers erzeuge.
Wenn diese Verzögerungen eine bestimmte Grenze (Größenordnung 5 sec)
überschreiten, werden die folgenden Zeichen zwar noch geschrieben,
werden aber erst sichtbar, wenn ein Stop durch eine Inputbox erfolgt.
Word arbeitet also im Hintergrund weiter.
Früher konnte man dies durch
Application.ScreenUpdating=False (bzw. True)
steuern. Diese Anweisung funktioniert aber nicht mehr.
Bei Access gibts ein Application.Echo False/True. Ohne = Zeichen.
Alternativ das gen. DoEvents. Du kannst natürlich auch ein DoEvents so
einbauen:

Dim GeöffneteFormulare

For f = 1 To 150000 ' Schleifenanfang.
If f Mod 1000 = 0 Then ' Nach 1000 Durchläufen Steuerung
GeöffneteFormulare = DoEvents ' an das Betriebssystem abgeben.
End If
Next f ' Schleifenzähler hochzählen.



Servus
Winfried
--
Connect2WSUS: http://www.grurili.de/tools/Connect2WSUS.exe
GPO's: http://www.gruppenrichtlinien.de
Community Forums NNTP Bridge: http://communitybridge.codeplex.com/
Reg2xml: http://www.reg2xml.com - Registry Export File Converter
Wolfram Jahn
2011-07-22 21:33:37 UTC
Permalink
Bei Access gibts [...]
Ja, aber leider hat der OP ein Problem in Word.


Wolfram
Manfred Berger
2011-07-23 07:53:23 UTC
Permalink
Hallo Winfried

Ich werde das gelegentlich ausprobieren und berichten.
Vielen Dank erst mal.

Hallo Wolfram

Ich arbeite noch dran, melde mich später wieder.

Servus
Manfred
Manfred Berger
2011-07-23 14:17:51 UTC
Permalink
Hallo Wolfram

Ich habe Dir das gewünschte Makro per E-Mail geschickt.

Servus
Manfred
Wolfram Jahn
2011-07-23 21:18:09 UTC
Permalink
Post by Manfred Berger
Ich habe Dir das gewünschte Makro per E-Mail geschickt.
Ahja.

Also, von sogenanntem 'Busy waiting', wie Du es da verwendest, wird ja
eigentlich abgeraten. Bei mir verbraucht Word dabei laut Task Manager
98%-99% der CPU Zeit. Damit könnte man sicher besseres anfangen als
Nanosekunden zu zählen.

Trotzdem läuft es bei mir, wenn ich direkt hinter die Ausgabeanweisung
WordBasic.Insert "a"
ein weiteres DoEvents einfüge.

Ganz stark empfehlen würde ich Dir jedoch eine Implementierung mittels
"Application.OnTime". Am besten wäre es dafür, wenn Du immer nur ganze
Sekunden warten müsstest. Wenn aber die Bruchteile für Dich essenziell
sind, dann würde ich zumindest die ganzen Sekunden mit OnTime abwarten
und dann nur den Sekunden-Bruchteil mit Deiner bisherigen Wartefunktion
abhandeln.

Der Rest Deiner laufenden Anwendungen (oder der Anwendungen Deiner
Kunden) wird es Dir danken, insbesondere auf Rechnern mit nur einer CPU.


Wolfram
Manfred Berger
2011-07-24 13:34:31 UTC
Permalink
On Sat, 23 Jul 2011 23:18:09 +0200, Wolfram Jahn <-***@arcor.de> wrote:

Hallo Wolfram
Post by Wolfram Jahn
hinter die Ausgabeanweisung
WordBasic.Insert "a"
ein weiteres DoEvents einfüge.
werde ich mal versuchen
Post by Wolfram Jahn
Ganz stark empfehlen würde ich Dir jedoch eine Implementierung mittels
"Application.OnTime".
Das kannte ich noch nicht, aber ich lerne gern noch hinzu. Hoffentlich
gibt die Hilfe genügend Information, sonst muß ich eben nochmal
nachfragen.
Post by Wolfram Jahn
Wenn aber die Bruchteile für Dich essenziell sind
Nein, sind sie nicht. Es hat sich nur so ergeben, damit die Ausgabe
möglichst deutlich (also nach dem 4. Zeichen) umgeschaltet wird.

Servus
Manfred
Manfred Berger
2011-07-24 15:49:15 UTC
Permalink
Hallo Wolfram
Post by Wolfram Jahn
Trotzdem läuft es bei mir, wenn ich direkt hinter die Ausgabeanweisung
WordBasic.Insert "a"
ein weiteres DoEvents einfüge.
Im meinem Makro gibt es nicht nur die Ausgabe von Buchstaben. Auch an
anderen Stellen soll gewartet werden. Z.B. kann eine bereits
ausgegebene Zeile nochmals für einige Zeit angezeigt werden.

Ich habe v o r der Timer-Abfrage im Sub noch ein DoEvents
eingefügt, muß aber noch probieren, ob die beobachtete zunehmende
Verzögerung damit nicht mehr auftritt. Dafür brauche ich viel Zeit :-(
Post by Wolfram Jahn
Ganz stark empfehlen würde ich Dir jedoch eine Implementierung mittels
"Application.OnTime".
Ich habe eine Anweisung
Application.OnTime when := Now + TimerValue("00:00:05"), name:= "test"
eingefügt. Irgendwie habe ich das noch nicht verstanden, denn das
Makro wartet nicht. Die Anwendung müßte ja zunächst verlassen werden,
bevor sie nach 5 Sekunden wieder aufgerufen wird?

Servus
Manfred
Wolfram Jahn
2011-07-24 22:19:56 UTC
Permalink
Post by Manfred Berger
Ich habe eine Anweisung
Application.OnTime when := Now + TimerValue("00:00:05"), name:= "test"
eingefügt. Irgendwie habe ich das noch nicht verstanden, denn das
Makro wartet nicht.
Falls Du den Schreibfehler hier drüber genauso in Deinem Code hast,
liegt es daran (Falsch:"TimerValue(..." statt richtig:"TimeValue(...").

Ansonsten läuft folgendes bei mir ungestört nebenbei vor sich hin (und
braucht alle Sekunde mal 2% CPU Zeit:)

Sub start_OnTime()
Application.OnTime Now + TimeValue("0:0:1"), "mach_weiter"
End Sub

Sub mach_weiter()
WordBasic.Insert "a"
Application.OnTime Now + TimeValue("0:0:1"), "mach_weiter"
End Sub



Wolfram
Manfred Berger
2011-07-24 22:31:06 UTC
Permalink
Hallo Wolfram
Post by Wolfram Jahn
Falls Du den Schreibfehler hier drüber genauso in Deinem Code hast,
liegt es daran (Falsch:"TimerValue(..." statt richtig:"TimeValue(...").
Ja, das war nur ein Tippfehler. Sonst würde Word wohl auch einen
Fehler melden.
Post by Wolfram Jahn
Ansonsten läuft folgendes bei mir ungestört nebenbei vor sich hin (und
braucht alle Sekunde mal 2% CPU Zeit:)
Danke für das Beispiel. Das Prinzip ist klar. Ich muß nun versuchen,
das in mein komplizierteres Programm einzubauen.

Servus
Manfred
Manfred Berger
2011-07-25 15:25:35 UTC
Permalink
Hallo Wolfram

Ich muß mich nochmal melden. Ich hab's einfach noch nicht kapiert.
Folgendes Programm bräuchte ich:

Dim n%
Sub atest()
'
' atest Makro
'
WordBasic.Insert "b"
n = 1: warte
WordBasic.Insert "c"
n = 2: warte
WordBasic.Insert "d"
End Sub

Sub warte()
WordBasic.Insert Str(n)
If n < 9 Then
n = 9
Application.OnTime Now + TimeValue("0:0:2"), "warte"
End If
End Sub

Aber das wartet zunächst nicht. Erst nachdem atest abgelaufen ist gibt
es die 9 nach etwa 2 sec aus.
Wo liegt der Fehler?

Servus
Manfred
Wolfram Jahn
2011-07-25 20:43:54 UTC
Permalink
Versuch dies:

Dim a
Dim n

Sub atest()
n = 1
a = Split("b 1 c 2 d 9")
ausgeben
End Sub

Sub ausgeben()
If n <= UBound(a) Then
WordBasic.Insert a(n)
n = n + 1
Application.OnTime Now + TimeValue("0:0:2"), "ausgeben"
Else
Debug.Print "Fertig"
End If
End Sub



Es ist immer spannend mit diesem nicht-sequentiellen Zeugs, es stellen
sich völlig ungewohnte Fragen:

Wo läuft gerade der Code?
Wie bekomme ich den Ablauf gesteuert?
Wie bekomme ich die Daten an die richtigen Stellen?
Wie höre ich richtig auf?


Wolfram
Manfred Berger
2011-07-27 06:33:43 UTC
Permalink
Hallo Wolfram

Das ist nicht das, was ich will. Bei Dir werden zuerst alle Ausgaben
berechnet und dann in einem 2. Programm ausgegeben.

Ich möchte eine Zeile berechnen (insgesamt sind es mehrere hundert),
diese sofort am Bildschirm anzeigen und dann irgendwo im Ablauf das
Programm für 1 bis 3 Sekunden aufhalten, ohne daß der Benutzer eine
Taste bedienen muß.

Servus
Manfred
Bernhard Sander
2011-07-27 09:48:26 UTC
Permalink
Hallo Manfred,
Post by Manfred Berger
Das ist nicht das, was ich will. Bei Dir werden zuerst alle Ausgaben
berechnet und dann in einem 2. Programm ausgegeben.
Ich möchte eine Zeile berechnen (insgesamt sind es mehrere hundert),
diese sofort am Bildschirm anzeigen und dann irgendwo im Ablauf das
Programm für 1 bis 3 Sekunden aufhalten, ohne daß der Benutzer eine
Taste bedienen muß.
Eine Warte-Funktion ist in VBA nicht vorhanden. Es gibt den Umweg über OnTime
wie Wolfram beschrieben hat.
Anderer Ausweg wäre, die Sleep-Funktion der Windows-Api aufzurufen. Wie das von
VBA aus zu bewerkstelligen ist weiß ich grad nicht, aber Google "VBA Sleep"

Gruß
Bernhard Sander
Manfred Berger
2011-07-28 15:55:30 UTC
Permalink
Hallo Bernhard
Post by Bernhard Sander
Eine Warte-Funktion ist in VBA nicht vorhanden. Es gibt den Umweg über OnTime
wie Wolfram beschrieben hat.
Ja, so funktioniert das auch, aber ich möchte es anders.
Post by Bernhard Sander
aber Google "VBA Sleep"
Habe ich getan und mehrere Seiten gefunden, die alle das gleiche
Vorgehen beschreiben:
Private Declare Sub Sleep Lib "kernel132" (ByVal dwMilliseconds As
Long)
Anschließend im Programm (für 2 sec Pause) nur:
sleep 2000
Das geht leider nicht so, weil die Datei kernel132 nicht gefunden
wird. Vermutlich muß ich dazu den genauen Ort angeben, finde ihn aber
nicht. Oder die Datei heißt bei Win7 anders.

Servus
Manfred
Bernhard Sander
2011-07-28 16:11:58 UTC
Permalink
Hallo Manfred,
Post by Manfred Berger
Habe ich getan und mehrere Seiten gefunden, die alle das gleiche
Private Declare Sub Sleep Lib "kernel132" (ByVal dwMilliseconds As Long)
die Lib heisst kernel32 , nicht kernel_1_32

Gruß
Bernhard Sander
Manfred Berger
2011-07-28 16:08:15 UTC
Permalink
OK, ich habe einen ersten Fehler gefunden -
nicht kernel132
sondern kernel32.

Aber jetzt heißt die Meldung: Einsprungpunkt sleep in kernel32 nicht
gefunden.
Manfred Berger
2011-07-28 16:28:55 UTC
Permalink
Tja, der nächste Fehler:
Sleep,
nicht sleep.

Jetzt geht's.

Danke!
Wolfram Jahn
2011-07-27 21:21:56 UTC
Permalink
Post by Manfred Berger
Das ist nicht das, was ich will.
Du musst natürlich ein bisschen kreativ werden mit der Programmlogik:


Sub berechnen()
Dim s, n%
' berechne irgendwas (hier kommt Dein ganzes Programm rein,
' natürlich nicht wörtlich, sondern aufgerufen;
' einen Status von Aufruf zu Aufruf musst Du
' Dir auch irgendwo merken)
'
' Nur als beliebiges Beispiel:
s = Split(Time, ":")(2)
n = (s Mod 20) / 6
'lass es ausgeben
WordBasic.Insert Time & ", warte " & n & " Sec" & vbCrLf
If n > 0 Then 'warten
Application.OnTime Now + TimeSerial(0, 0, n), "weiter"
End If
End Sub

Sub weiter()
Application.OnTime Now + TimeSerial(0, 0, 0), "berechnen"
End Sub


(Das ergab die denkwürdige Ausgabe von:)
----------------------------------------
23:14:25, warte 1 Sec
23:14:26, warte 1 Sec
23:14:27, warte 1 Sec
23:14:28, warte 1 Sec
23:14:29, warte 2 Sec
23:14:31, warte 2 Sec
23:14:33, warte 2 Sec
23:14:35, warte 2 Sec
23:14:37, warte 3 Sec
23:14:40, warte 0 Sec
----------------------------------------


Aber das von Bernhard empfohlene Sleep passt Dir sicher besser.

Wolfram
Manfred Berger
2011-07-28 16:00:22 UTC
Permalink
Hallo Wolfram
Ja, seufz.
Post by Wolfram Jahn
Sub berechnen()
....
Post by Wolfram Jahn
End Sub
Das muß ich erst mal verdauen :o)
Post by Wolfram Jahn
Aber das von Bernhard empfohlene Sleep passt Dir sicher besser.
Ja, ich arbeite noch dran (s. Post an Bernhard).

Servus
Manfred
Manfred Berger
2011-07-28 16:53:38 UTC
Permalink
Endlich: Problem gelöst!

Nochmals herzlichen Dank Euch Beiden
für Eure Hilfe und vor allem
für Eure Geduld mit einem Anfänger.

Servus
Manfred

Lesen Sie weiter auf narkive:
Loading...