Autor Beitrag
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 25.06.17 06:51 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 25.06.17 10:26 
Hallo,

das war mir schon bei deinem anderen Beitrag dazu aufgefallen: das ist kein gutes Design mit der statischen Methode MainClass.WndProc, da sich die beiden Klassen gegenseitig referenzieren.

Ich würde ein Event (bzw. Delegat) in WndClass deklarieren und mittels der MainClass daran binden (und diese kann dann wiederum eine virtuelle Methode aufrufen).
Hier (in Kürze) der Code dazu:
ausblenden volle Höhe C#-Quelltext
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:
29:
30:
31:
32:
public class MainClass
{
    public MainClass()
    {
        _wndClass = new WndClass();
        _wndClass.OnWndProc = OnWndProc;
    }

    protected void OnWndProc(ref Message m)
    {
        WndProc(ref m);
    }

    protected virtual void WndProc(ref Message m)
    {
        // ...
    }
}

class WndClass : NativeWindow 
{
    public delegate void WndProcDelegate(ref Message m);

    public WndProcDelegate OnWndProc;

    protected override void WndProc(ref Message m)
    {
        OnWndProc?.Invoke(ref m);

        base.WndProc(ref m);
    }
}

(falls dir ?. nichts sagt, dies ist ab C# 6 möglich: Null-Conditional Operator - ansonsten einfach wie in deinen bisherigen OnDo...-Methoden aufrufen)

Und die MainClass-Ereignisse dann nicht-statisch deklarieren.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 26.06.17 01:26 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 26.06.17 09:04 
Nur noch als Hinweis. Die C#-Version (also welchen Compiler du nutzt) hat nichts mit dem eingesetzten .NET-Framework zu tun...
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mo 26.06.17 09:10 
Und noch ein Hinweis :D

Die korrekte Umsetzung des ?-Operators ist:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
OnWndProc?.Invoke(ref m);
// wird zu
var tmp = OnWndProc;
if (tmp != null)
    tmp.Invoke(ref m);

Dann ist es auch thread-safe ;)

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 26.06.17 09:22 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mo 26.06.17 09:33 
Ohne die temporäre Variable könnte zwischen der if-Abfrage und dem Invoke ein anderer Thread das Feld nullen und es würde eine NullReferenceException geben. Durch die temporäre, lokale Variable kann ein anderer Thread nicht mehr zugreifen.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 26.06.17 09:34 
Wenn genau zwischen den 2 Zeilen ein Threadwechsel stattfindet und dann die interne Eventmethoden-Liste geändert wird (im schlimmsten Fall das letzte Element gelöscht wird => Liste ist dann doch null => NullReferenceException).
Ob man das Event-De-/Abonnieren aber aus verschiedenen Threads überhaupt verwenden sollte, ist für mich eher designtechnisch zu hinterfragen.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 26.06.17 12:06 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 26.06.17 20:10 
Zitat:
Das gibt mir doch etwas zu denken, ob nicht auch andere Delphi und C# Projekte davon betroffen sind.


Das gilt eigentlich in jedem System. Sobald etwas prüfen und dann etwas mit dem geprüften tun 2 Dinge (nicht atomar) sind hat man ein potentielles Threading Problem.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 27.06.17 07:47 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 27.06.17 09:38 
Die einzige Referenz auf das neu erzeugte Array hat jetzt die Beispiel Methode insofern ist das potentiell ungefährlich.

Denn Zusammenhang zum vorher besprochenen verstehe ich aber nicht ganz :gruebel:
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 27.06.17 09:55 
- Nachträglich durch die Entwickler-Ecke gelöscht -