2009-03-29 3 views
5

je le code suivant:Passage de données dans une méthode de rappel (via BeginInvoke) en C#

delegate int doStuffDel(int instanceNo, int sleepTime, int repeatCount); 
    string result; 

    private int doStuff(int instanceNo, int sleepTime, int repeatCount) 
    { 
     for (int i = 0; i < repeatCount; i++) 
     { 
      Console.Write(instanceNo); 
      Thread.Sleep(sleepTime); 
     } 
     result = instanceNo + " repeated " + repeatCount; 
     return instanceNo; 
    } 

    private void button3_Click(object sender, EventArgs e) 
    { 
     doStuffDel del = doStuff; 
     IAsyncResult ar = del.BeginInvoke(3, 120, 50, finishedCallback, result); 
    } 

    private void finishedCallback(IAsyncResult ar) 
    { 
     Console.WriteLine("Done. The result was " + ar.AsyncState.ToString()); 
    } 

Je pensais que le res.AsyncState retournerait la chaîne, passé comme dernier argument dans l'appel à BeginInvoke, mais c'est nul. Est-ce que quelqu'un sait pourquoi? PS, je sais que je pourrais passer le del comme dernier argument dans BeginInvoke et ensuite appeler EndInvoke dans le rappel, pour obtenir un résultat de la méthode doStuff, - ou je pourrais juste obtenir la chaîne val de la classe! - mais je suis surpris que l'AsyncState sur l'objet AsyncResult soit nul ...

+1

Appelez toujours EndInvoke sur un IAsyncResult, sinon vous risquez de perdre des ressources non gérées (événements). –

Répondre

8

La valeur de ar.AsyncState est la valeur du résultat lorsque vous l'avez initialement transmise à BeginInvoke. Le fait que lorsque vous l'avez passé, vous avez utilisé la valeur result ne signifie pas qu'il est "lié" à la variable résultat. C'est juste la valeur de la variable result lorsque vous la transmettez pour commencer.

Pour ce faire, définissez result sur une valeur de test avant d'appeler BeginInvoke, ou passez simplement un littéral de chaîne à la place. De toute façon, vous aurez cette valeur dans le rappel. D'autre part, votre callback et votre délégué d'origine ont tous deux le même objet cible, donc vous pouvez utiliser result dans le rappel et il aurait la valeur que vous voulez - c'est une autre façon de maintenir l'état.

1

Il est transmis lorsque vous appelez BeginInvoke. À ce moment-là, résultat est null. Si vous définissez résultat avant l'appel, vous le verrez dans le rappel.

1

Le problème est que vous passez la valeur de result - qui (avant doStuff) est null. Les mises à jour vers result au sein de doStuff n'affectent pas l'état asynchrone.

Questions connexes