Autor Beitrag
j0sh
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mi 14.04.10 11:42 
Hallo Leute,

ich beschäftige mich jetzt seit ein paar Tagen mit Threads und komme gerade nicht weiter.
Ich lasse eine Zeitaufwendige Methode in einem eigenen Thread laufen. Dieser Methode übergebe ich am Anfang zwei Parameter und lasse den Thread nach fertigstellung der Methode die Methode "Callbackhandler" aufrufen um mit der Codeverarbetung im MainThread fortzufahren. Nun schaffe ich es aber nicht den Returnwert (bool) von dem Thread zu erhalten bzw. diesen zu beenden.
Hier bekomme ich Folgende Fehlermeldung:
ausblenden C#-Quelltext
1:
2:
3:
           
// Keine Überladung für die EndInvoke-Methode nimmt 1 Argumente an. 
bool allgood = GetDistinguishedNameAsync.EndInvoke(result);


Ich fang mit der Fehlerbeschreibung leider nichts an und wenn ich im weiteren verlauf der Methode in meine textBox etwas schreiben möchte dann bekomme ich einen Fehler das ich das nur im MainThread kann - dachte da wäre ich nun / der zweite Thread wurde doch beendet?!


Hier nochmal der Code aufs wesentliche reduziert ;)
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
        public delegate bool AsyncDelegate(GetDistinguishedName.objectClass objectClass, ref ElementStruktur struktur);

        private void button1_Click(object sender, EventArgs e)
        {
            AsyncDelegate GetDistinguishedNameAsync = new AsyncDelegate(GetDistinguishedName.GetObjectDistinguishedName);

            IAsyncResult asyncResult = GetDistinguishedNameAsync.BeginInvoke(GetDistinguishedName.objectClass.user, ref Struktur1, new AsyncCallback(CallbackHandler), GetDistinguishedNameAsync);
        }

        public  void CallbackHandler(IAsyncResult result)
        {
            // aus (IAsyncResult) asyncResult die AsyncDelegate-Instanz extrahieren
            AsyncDelegate GetDistinguishedNameAsync = (AsyncDelegate)result.AsyncState;

            // Beenden der AsyncVerarbeitung / Resultat erhalten.
            bool allgood = GetDistinguishedNameAsync.EndInvoke(result);

            //.....weitere Verarbeitung..
            // TextBox-Aufruf!
        }


p.s.
Die Methode "GetObjectDistinguishedName" gibt einen bool zurück, Name ist etwas unglücklich gewählt :(

Edit1:
Habe nun herausgefunden das es am "ref" liegt. Verstehe zwar nicht wiso und wäre froh wenn mir das jemand erklären könnte aber ich hab die "Struktur1" nun nichtmehr übergeben und statdessen beim starten des zweiten Threads erzeugt und sie mir anschliesend als Rückgabeparam. ausgeben lassen :-)
Habe aber nach wie vor das Problem das er scheinbar den Thread nicht beendet. Nach dem erfolgreichen ausführen von *.EndInvoke(result) mekert er trotzdem das ich auf Steuerelemente keinen Zugriff habe :-(
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Mi 14.04.10 13:50 
Bin nur kurz drüber geflogen, aber was du mit ref oder out reinschiebst, musst du auch wieder rausholen. Also entsprechend:
ausblenden C#-Quelltext
1:
.EndInvoke(ref strukture, result);					
j0sh Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mi 14.04.10 14:11 
user profile iconj0sh hat folgendes geschrieben Zum zitierten Posting springen:

Habe aber nach wie vor das Problem das er scheinbar den Thread nicht beendet. Nach dem erfolgreichen ausführen von *.EndInvoke(result) mekert er trotzdem das ich auf Steuerelemente keinen Zugriff habe :-(


Bestimmt nicht die schönste Lösung aber sie tut:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
        public void CallbackHandler(IAsyncResult result)
        {
            if (treeView1.InvokeRequired == true)
            {
                BuildTreeDelegate callback = new BuildTreeDelegate(BuildTree);
                this.Invoke(callback, "pfad");
            }
            else BuildTree("pfad");
        }

        delegate void BuildTreeDelegate(String path);

        public void BuildTree(String Path)
        {
             ...
        }


Habe also über ein Delegate einfach auf den Thread zugegriffen der das Handle an den Objekten hällt :-)
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 14.04.10 19:25 
Ehrlich gesagt habe ich noch nie den Sinn in diesen asynchronen Delegates gesehen, da spreche ich lieber direkt den Threadpool an ;) .
Mein Vorschlag eines Standard-"GUI-Nebenthread-GUI"-Templates:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
ThreadPool.QueueUserWorkItem(delegate {
  var x = DoSomethingExpensive();
  /*Begin*/Invoke((Action) delegate {
    ShowInGui(x);
  });
});

Und seit .NET 4 über die Task Parallel Library besser:
ausblenden C#-Quelltext
1:
2:
3:
Task.Factory.StartNew(() => {
  return DoSomethingExpensive();
}).ContinueWith(ShowInGui, TaskScheduler.FromCurrentSynchronizationContext());

Der Vorteil ist daran, dass Exceptions automatisch in den GUI-Thread überführt werden, während man ohne TPL selbst dafür sorgen müsste.

_________________
>λ=