Forums Neueste Beiträge
 

Einer geht noch...: Control.Invoke

04/06/2010 - 18:46 von Armin Zingler | Report spam
Hi,

[viel Text gelöscht...]

Problem: Control.Invoke kehrt nie zurück wenn das Fensterhandle
bereits zerstört wurde. Ich erwarte aber eine Exception.

Aufgrund Multithreading war das Problem zunàchst schwer nachzuvollziehen.
Dann habe ich zwecks Fehlersuche vorsàtzlich darauf gewartet, dass das
Handle beim Invoke bereits zerstört ist. So wie bei diesem Testcode:


Public Class Main

Class MyForm : Inherits Form
Protected Overrides Sub OnHandleDestroyed(ByVal e As System.EventArgs)
MyBase.OnHandleDestroyed(e)
flag.Set()
End Sub
End Class

Shared flag As New Threading.AutoResetEvent(False)
Shared f As New myform
Shared tmr As New Windows.Forms.Timer

Shared Sub main()

Dim t As Threading.Thread

t = New Threading.Thread(AddressOf tmain)
t.Name = "worker"
t.Start()

tmr.Interval = 1000
AddHandler tmr.Tick, AddressOf OnTick
tmr.Start()

Application.Run(f)

End Sub
Shared Sub tmain()
flag.WaitOne()
f.Invoke(New MethodInvoker(AddressOf InvokeTarget))
End Sub
Shared Sub OnTick(ByVal sender As Object, ByVal e As System.EventArgs)
tmr.Stop()
f.Close()
End Sub
Shared Sub InvokeTarget()

End Sub
End Class


Hier kommt die erwartete Exception. Im eigentlichen Projekt aber nicht.

Ideen? :-)

Und welche Gruppe wàre dafür jetzt die beste? d.c.o.ms-windows.programmer?

Armin
 

Lesen sie die antworten

#1 Thomas Scheidegger
04/06/2010 - 21:47 | Warnen spam
Hallo Armin

Problem: Control.Invoke kehrt nie zurück
wenn das Fensterhandle bereits zerstört wurde.



Ursache müsste man genauer untersuchen,
aber besser
(uU wg wackliger MS Implementation)
wàre wohl diese Konstellation zu vermeiden...

Am 'saubersten' wàre es wohl,
schon im 'FormClosing'-Eventhandler ggf noch laufenden Worker-Thread(s)
das Ende zu 'signalisieren'
(wie auch immer, zB Flags, BackgroundWorker.CancelAsync, AutoResetEvent
uà)
aber den Close-Vorgang hier vorerst abbrechen
(=FormClosingEventArgs.Cancel).
[damit Window-Handle bestehen bleibt!]
Das effektive Beenden des Worker-Threads kann dieser
per Invoke (oder RunWorkerCompleted-Event) wieder dem GUI-Thread
zurückmelden, wo dann das Form endgültig
geschlossen werden kann (etwa per Close Aufruf).
Ggf braucht es einen 'Merker' und/oder andere 'Buchhaltung',
etwa im FormClosing-Handler ob 1. oder 2. Close im Gange ist, ua.

Falls dieser Prozess (wegen 'tràgen' Worker-Threads)
etwas dauert, könnte man derweil auch Sanduhr anzeigen
und ggf Eingabe-Steuerelemente auf Form disablen, oà.


Thomas Scheidegger - 'NETMaster'
http://dnetmaster.net/

Ähnliche fragen