<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://www.dotnetzone.gr:443/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>.NET Framework</title><link>https://www.dotnetzone.gr:443/cs/forums/14/ShowForum.aspx</link><description>Θέματα για threading, remoting, reflection, exception handling, security, regex κλπ.</description><dc:language>el</dc:language><generator>CommunityServer 2.1 SP3 (Build: 20423.1)</generator><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/70257.aspx</link><pubDate>Wed, 16 May 2012 18:00:47 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:70257</guid><dc:creator>Παναγιώτης Καναβός</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/70257.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=70257</wfw:commentRss><description>&lt;p&gt;Δοκίμασα το Retry με async στο Visual Studio 2011 και η μορφή με το while δουλεύει, ενώ η recursive μορφή που αντιστοιχεί στην F# θέλει μία μικρή αλλαγή.&lt;/p&gt;&lt;p&gt;Το παρακάτω δουλεύει:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:black;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;        &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;private&lt;/span&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;static&lt;/span&gt; async Task&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; func, &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;int&lt;/span&gt; retryCount)
        {
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;while&lt;/span&gt; (&lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;true&lt;/span&gt;)
            {
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;try&lt;/span&gt;
                {
                    var result &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;=&lt;/span&gt; await Task.Run(func);
                    &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;return&lt;/span&gt; result;
                }
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;catch&lt;/span&gt;
                {
                    &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (retryCount == 0)
                        &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;throw&lt;/span&gt;;
                    retryCount--;
                }
            }
        }&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Αυτή η έκδοση όμως δεν δουλεύει, γιατί δεν γίνεται δεκτό το await μέσα στο catch:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:black;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;        &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;private&lt;/span&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;static&lt;/span&gt; async Task&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; func, &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;int&lt;/span&gt; retryCount)
        {
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;try&lt;/span&gt;
            {
                var result &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;=&lt;/span&gt; await Task.Run(func);
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;return&lt;/span&gt; result;
            }
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;catch&lt;/span&gt;
            {
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (retryCount == 0)
                    &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;throw&lt;/span&gt;;
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;return&lt;/span&gt; await Retry(func, --retryCount);
            }
        }&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Ευτυχώς, μπορούμε άνετα να κάνουμε το Retry έξω από το catch, οπότε η παρακάτω μορφή δουλεύει:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:black;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;        &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;private&lt;/span&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;static&lt;/span&gt; async Task&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; func, &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;int&lt;/span&gt; retryCount)
        {
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;try&lt;/span&gt;
            {
                var result &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;=&lt;/span&gt; await Task.Run(func);
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;return&lt;/span&gt; result;
            }
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;catch&lt;/span&gt;
            {
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (retryCount == 0)
                    &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;throw&lt;/span&gt;;
            }
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;return&lt;/span&gt; await Retry(func, --retryCount);
        }&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/70213.aspx</link><pubDate>Mon, 07 May 2012 19:48:45 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:70213</guid><dc:creator>Παναγιώτης Καναβός</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/70213.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=70213</wfw:commentRss><description>&lt;p&gt;Έχεις δίκιο, στον έλεγχο του RetryCount λείπει το else. Έπρεπε να είναι &lt;/p&gt;&lt;pre&gt;&lt;span style="color:black;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;&lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (retryCount == 0)
    tcs.SetException(_original.Exception.InnerExceptions);
 &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;else&lt;/span&gt;
    Retry(func, retryCount &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;-&lt;/span&gt; 1, tcs);&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;αντί για&lt;/p&gt;&lt;pre&gt;&lt;span style="color:black;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;&lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (retryCount == 0)
    tcs.SetException(_original.Exception.InnerExceptions);
Retry(func, retryCount &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;-&lt;/span&gt; 1, tcs);&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Στον κώδικα του Νίκου έχεις κάνει μία "κακή" αλλαγή. Η προσθήκη του Thread.Sleep θα προκαλέσει πρόβλημα γιατί&amp;nbsp;αχρηστεύει &amp;nbsp;ένα thread από το thread pool. Σκοπός του TPL είναι να απαλλαγούμε από απευθείας παρεμβάσεις στα threads. &lt;/p&gt;&lt;p&gt;Αν θέλεις να προσθέσεις κάποια καθυστέρηση, θα πρέπει να χρησιμοποιήσεις tasks για να κάνεις κάτι σαν την &lt;a href="http://blogs.msdn.com/b/pfxteam/archive/2009/06/03/9691796.aspx"&gt;StartNewDelayed&lt;/a&gt; από τα ParallelExtensionExtras για να εκτελέσεις το Retry αφού περάσει το timeout. Σε αυτή την περίπτωση ο κώδικας αλλάζει στο παρακάτω:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:black;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;private&lt;/span&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;static&lt;/span&gt; Task&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; func, &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;int&lt;/span&gt; retryCount, &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;int&lt;/span&gt; delay, TaskCompletionSource&amp;lt;T&amp;gt; tcs &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;=&lt;/span&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;null&lt;/span&gt;)
        {
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (tcs == &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;null&lt;/span&gt;)
                tcs &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;=&lt;/span&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;new&lt;/span&gt; TaskCompletionSource&amp;lt;T&amp;gt;();
            Task.Factory.StartNew(func).ContinueWith(_original =&amp;gt;
            {
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (_original.IsFaulted)
                {
                    &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (retryCount == 0)
                        tcs.SetException(_original.Exception.InnerExceptions);
                    &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;else&lt;/span&gt;
                        Task.Factory.StartNewDelayed(delay).ContinueWith(t =&amp;gt;
                        {
                            Retry(func, retryCount &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;-&lt;/span&gt; 1, delay,tcs);
                        });
                }
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;else&lt;/span&gt;
                    tcs.SetResult(_original.Result);
            });
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;return&lt;/span&gt; tcs.Task;
        }&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Αυτό που προσπαθώ να κάνω να παίξει και κάτι πάει στραβά, είναι το Retry με async/await. Κανονικά ο παρακάτω κώδικας&amp;nbsp; θα έπρεπε να παίζει αλλά κρεμάει χωρίς καν unhandled exception, όταν κάνω compile σε Visual Studio 2010 με Async CTP.&lt;/p&gt;&lt;pre&gt;&lt;span style="color:black;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;&lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;private&lt;/span&gt; &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;static&lt;/span&gt; async Task&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; func, &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;int&lt;/span&gt; retryCount)
{
    &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;while&lt;/span&gt; (&lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;true&lt;/span&gt;)
    {
        &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;try&lt;/span&gt;
        {
            var result &lt;span style="color:red;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;=&lt;/span&gt; await TaskEx.Run(func);
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;return&lt;/span&gt; result;
        }
        &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;catch&lt;/span&gt; 
        {
            &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;if&lt;/span&gt; (retryCount == 0)
                &lt;span style="color:blue;font-family:Courier New;font-size:11px;font-weight:normal;background-color:transparent;"&gt;throw&lt;/span&gt;;
            retryCount--;
        }
    }
}&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Υποθέτω ότι το rewriting που κάνει ο compiler τουλάχιστον στο Async CTP αποτυγχάνει όταν δει παραπάνω από δύο exceptions στο catch. Επίσης, δεν μπορώ να έχω await μέσα στο catch, κάνοντας το Delay επίσης δύσκολο. Κρίμα, αν έπαιζε το Retry θα ήταν τόσο καθαρό όσο η αρχική έκδοση!&lt;/p&gt;&lt;p&gt;Όταν ο compiler συναντάει τα async/await keywords στην ουσία δημιουργεί ένα task iterator ο οποίος τρέχει ως ξεχωριστό task τον κώδικα μεταξύ των awaits. Τα πράγματα γίνονται δύσκολα όταν υπάρχει catch/finally και παρότι ο compiler κάνει αρκετά καλή δουλειά, δεν μπορείς να έχεις await μέσα σε catch ή finally, ενώ όπως φαίνεται παραπάνω, τα απανωτά exception προκαλούν εγκεφαλικό.&lt;/p&gt;&lt;p&gt;Όπως θα πει και ο Νίκος, το async της F# είναι ανώτερο από το αντίστοιχο του .NET &lt;img src="http://www.dotnetzone.gr/cs/emoticons/emotion-6.gif" alt="Sad" /&gt;&lt;/p&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/70154.aspx</link><pubDate>Sun, 29 Apr 2012 05:13:45 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:70154</guid><dc:creator>georgiosd</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/70154.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=70154</wfw:commentRss><description>Παναγιώτη η πρώτη σου τεχνική (δεν δοκίμασα την δεύτερη), κολλάει κάπου και τρέχει τον κώδικα για πάντα εφόσον συνεχίσει να "σκάει"&lt;br&gt;&lt;br&gt;Παραθέτω εδώ την έκδοση του Νίκου αλλά με καθορισμό ενός Action σε περίπτωση που μετά το τέλος των retry δεν έχει επιτύχει, ώστε να μην κάνει throw o finalizer&lt;br&gt;&lt;br&gt;&lt;pre style="font-family:Consolas;font-size:15;color:black;background:white;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;lt;T&amp;gt;&amp;nbsp;Retry&amp;lt;T&amp;gt;(&lt;span style="color:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;T&amp;gt;&amp;nbsp;original,&amp;nbsp;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;nbsp;tryCount,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;Exception&lt;/span&gt;&amp;gt;&amp;nbsp;ifAllRetriesFail,&amp;nbsp;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;nbsp;delayMs&amp;nbsp;=&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;.Factory.StartNew(original).ContinueWith(_original&amp;nbsp;=&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;if&lt;/span&gt;&amp;nbsp;(_original.IsFaulted)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green;"&gt;//&amp;nbsp;call&amp;nbsp;this&amp;nbsp;so&amp;nbsp;that&amp;nbsp;TPL&amp;nbsp;thinks&amp;nbsp;we've&amp;nbsp;caught&amp;nbsp;all&amp;nbsp;the&amp;nbsp;exceptions&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;flattened&amp;nbsp;=&amp;nbsp;_original.Exception.Flatten();
 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green;"&gt;//&amp;nbsp;assume&amp;nbsp;it's&amp;nbsp;faulted&amp;nbsp;because&amp;nbsp;of&amp;nbsp;the&amp;nbsp;options&amp;nbsp;we&amp;nbsp;specify&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green;"&gt;//&amp;nbsp;for&amp;nbsp;ContinueWith()&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;if&lt;/span&gt;&amp;nbsp;(tryCount&amp;nbsp;==&amp;nbsp;1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green;"&gt;//&amp;nbsp;this&amp;nbsp;is&amp;nbsp;one&amp;nbsp;so&amp;nbsp;we&amp;nbsp;control&amp;nbsp;the&amp;nbsp;total&amp;nbsp;number&amp;nbsp;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green;"&gt;//&amp;nbsp;of&amp;nbsp;tries&amp;nbsp;and&amp;nbsp;not&amp;nbsp;retries&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ifAllRetriesFail(flattened.InnerException);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;.Factory.StartNew(()&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span style="color:blue;"&gt;default&lt;/span&gt;(T));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green;"&gt;//&amp;nbsp;sleep&amp;nbsp;baby&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Thread&lt;/span&gt;.Sleep(delayMs);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;Retry(original,&amp;nbsp;tryCount&amp;nbsp;-&amp;nbsp;1,&amp;nbsp;ifAllRetriesFail);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;lt;T&amp;gt;.Factory.StartNew(()&amp;nbsp;=&amp;gt;&amp;nbsp;_original.Result);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}).Unwrap();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/pre&gt;&lt;br&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67418.aspx</link><pubDate>Tue, 20 Sep 2011 19:22:27 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67418</guid><dc:creator>Παναγιώτης Καναβός</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67418.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67418</wfw:commentRss><description>Το σκάλισα λίγο παραπάνω και βρήκα ένα τρόπο να αποφύγω το Unwrap αλλά και το&amp;nbsp;return Task.Factory.StartNew(() =&amp;gt; _original.Result); το οποίο υπάρχει μόνο για να γυρίσει το έτοιμο αποτέλεσμα σε μορφή Task. Ο παρακάτω κώδικας χρησιμοποιεί το TaskCompletionSource, μία κλάση η οποία επιστρέφει ένα task το οποίο ολοκληρώνεται μόνο αν κάποιος καλέσει τις μεθόδους SetResult, SetException, SetCancelled :&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span style="background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;&lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; &lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; Task&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; func, &lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; retryCount,TaskCompletionSource&amp;lt;T&amp;gt; tcs=&lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;null&lt;/span&gt; )
{
&lt;span style="background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;    if&lt;/span&gt; (tcs==&lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;null&lt;/span&gt;)
        tcs=&lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; TaskCompletionSource&amp;lt;T&amp;gt;();
    Task.Factory.StartNew(func).ContinueWith(_original =&amp;gt;
    {
        &lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (_original.IsFaulted)
        {
            &lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (retryCount == 0)
                tcs.SetException(_original.Exception.InnerExceptions);
            Retry(func, retryCount &lt;span style="color:red;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;-&lt;/span&gt; 1,tcs);
        }
        &lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;else&lt;/span&gt;
            tcs.SetResult(_original.Result);
    });
    &lt;span style="color:blue;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; tcs.Task;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;To default property μπαίνει για να μην αλλάξει ο τρόπος κλήσης της Retry. Νομίζω ότι αυτή η μορφή είναι λίγο καθαρότερη αν ξέρεις τί κάνει το TaskCompletionSource&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Τέλος, άλλος ένας τρόπος είναι να χρησιμοποιηθεί η Task.Factory.Iterate από τα &lt;a href="http://blogs.msdn.com/b/pfxteam/archive/2010/04/04/9990342.aspx"&gt;ParallelExtensionsExtras&lt;/a&gt;, η οποία εκτελεί κάθε Task σε ένα IEnumerable&amp;lt;Task&amp;gt;. Εδώ το τρυκ είναι να μετατρέψεις τα retry σε ένα iterator όπως φαίνεται παρακάτω:&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; Task&amp;lt;T&amp;gt; RetryIterativeTCS&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; func, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; retryCount)
{
	var tcs=&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; TaskCompletionSource&amp;lt;T&amp;gt;();
	Task.Factory.Iterate(RetryIterator(func, retryCount, tcs));
	&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; tcs.Task;
}

&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; RetryIterator&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; original, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; retryCount, TaskCompletionSource&amp;lt;T&amp;gt; tcs)
{
	&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;while&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;true&lt;/span&gt;)
	{
		var task &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; Task&amp;lt;T&amp;gt;.Factory.StartNew(original);
		yield &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; task;

		&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (task.IsFaulted)
		{
			&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (retryCount == 0)
			{
				tcs.SetException(task.Exception.InnerExceptions);
				&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;break&lt;/span&gt;;
			}
			retryCount--;
		}
		&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;else&lt;/span&gt;
		{
			tcs.SetResult(task.Result);
			&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;break&lt;/span&gt;;
		}
	}
}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;To TCS μπαίνει για να μπορέσω να πάρω το αποτέλεσμα του function αν πετύχει, καθώς η Iterate επιστρέφει απλά ένα Task.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Η αλήθεια είναι ότι τον τελευταίο τρόπο τον έγραψα πιο πολύ για να δω πως γίνεται καθώς έχει μερικά προβλήματα:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Χρειάζεται άλλο ένα function, το RetryIterator&lt;/li&gt;&lt;li&gt;Χρειάζεται άλλο ένα library, το ParallelExtensionExtras&lt;/li&gt;&lt;li&gt;Χρειάζεται την Task.Factory.Iterate, η οποία ως υλοποίηση είναι λίγο πιο βαρειά από ένα StartNew&lt;/li&gt;&lt;li&gt;Η χρήση του iterator με αυτό τον τρόπο μπερδεύει όποιον δεν την έχει συνηθίσει&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Από την άλλη, είναι ευκολότερο να προσθέσει κανείς επιπλέον δυνατότητες στον RetryIterator, όπως αυξανόμενη καθυστέρηση μεταξύ των retry, χωρίς να πρέπει να προσθέσει παραμέτρους (π.χ. delay) στο signature της Retry.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Σχόλια?&lt;/div&gt;&lt;/div&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67321.aspx</link><pubDate>Fri, 16 Sep 2011 03:34:00 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67321</guid><dc:creator>Panagiotis Kefalidis</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67321.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67321</wfw:commentRss><description>Α να γεια σου ντε! &lt;img src="http://www.dotnetzone.gr/cs/emoticons/emotion-2.gif" alt="Big Smile" /&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67320.aspx</link><pubDate>Fri, 16 Sep 2011 03:27:15 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67320</guid><dc:creator>PALLADIN</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67320.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67320</wfw:commentRss><description>&lt;div&gt;And &amp;nbsp;this is my attempt in&amp;nbsp;C#&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; Task&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; original, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; retryCount)
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; 
                &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;"&gt;Task.Factory.StartNew(() =&amp;gt; original())&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;"&gt;.ContinueWith(_original =&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;                    {
                        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (_original.IsFaulted)
                        {
                            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (retryCount == 0)
                                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;throw&lt;/span&gt; _original.Exception;
                            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; Retry(original, retryCount &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;-&lt;/span&gt; 1);
                        }
                        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;else&lt;/span&gt;
                            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; Task.Factory.StartNew(() =&amp;gt; _original.Result);
                    }).Unwrap();
        }&lt;/span&gt;&lt;/pre&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67319.aspx</link><pubDate>Fri, 16 Sep 2011 02:55:51 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67319</guid><dc:creator>Panagiotis Kefalidis</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67319.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67319</wfw:commentRss><description>Νίκο, αμα ήταν να το κάνουμε σε άλλη γλώσσα ή με "πειραματικές" εκδόσεις (για την C#), τότε οκ.. Το θέμα οτι πρέπει να είναι ασύγχρονα, το ξέραμε απο την αρχή, αλλά η C#, ασύγχρονα έχει στην 5.. ή αμα περάσεις την CTP.. που δεν νομίζω να το θες (εννοώ με παρόμοιο syntax όπως η F#). Αλλοιώς η υλοποίηση πάει σε F# που λέει ο Νίκος, και το βγάζεις σαν Librabry?</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67314.aspx</link><pubDate>Fri, 16 Sep 2011 01:06:07 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67314</guid><dc:creator>PALLADIN</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67314.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67314</wfw:commentRss><description>&lt;div&gt;Νομίζω ότι αυτό που χρειάζεσαι είναι Async composition, δηλαδή να αποφύγεις τις blocking κλήσεις.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Μια απλή λύση σε F#&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;let retry (asyncComputation : Async&amp;lt;'T&amp;gt;) (retryCount : &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt;) : Async&amp;lt;'T&amp;gt; &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; 
    let rec retry' retryCount &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; 
        async {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;try&lt;/span&gt;
                let! result &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; asyncComputation  
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; result
            with exn -&amp;gt;
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; retryCount &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; 0 then
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; raise exn
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;else&lt;/span&gt;
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt;! retry' (retryCount &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;-&lt;/span&gt; 1)
        }
    retry' retryCount&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67313.aspx</link><pubDate>Fri, 16 Sep 2011 01:05:51 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67313</guid><dc:creator>Παναγιώτης Καναβός</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67313.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67313</wfw:commentRss><description>Το Wait σημαίνει καταρχήν ότι το thread που καλεί θα μπλοκάρει σε ένα ή περισσότερα σημεία. Επιπλέον, με εμποδίζει να να αλλάξω το signature της μεθόδου και να επιστρέψω π.χ. Task&amp;lt;T&amp;gt;. Να επιστρέψω απευθείας το task δεν γίνεται γιατί δεν έχω τρόπο να δω αν έχει πετύχει ή όχι. Θα μπορούσα για παράδειγμα να βάλω ένα ContinueWith αλλά εκεί μέσα δεν μπορώ να κάνω κάποιο loop ή επανεκτέλεση του ίδιου task.&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Το ιδανικό θα ήταν να γίνεται όλο το Retry ως ανεξάρτητα tasks και το function να μου επιστρέφει ένα task που θα καλύπτει όλα τα άλλα. Έτσι θα μπορούσα π.χ. να αποθηκεύσω τα αποτελέσματα σε ένα ContinueWith αντί να κάνω wait και να περιμένω.&lt;/div&gt;</description></item><item><title>Απ: Παράλληλο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67310.aspx</link><pubDate>Fri, 16 Sep 2011 00:18:46 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67310</guid><dc:creator>Panagiotis Kefalidis</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67310.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67310</wfw:commentRss><description>&lt;p&gt;Είτε με τον ένα, είτε με τον άλλο τρόπο, εφόσον πρόκειται για Retry (δηλαδή fail το προηγούμενο και try again) θα πρέπει να περιμένεις για να δεις αμα απέτυχε ή πέτυχε, αλλοιώς θες κώδικα για να δεις εάν πετύχανε και τα δύο κλπ.. Και το Wait γιατι δεν σ'αρεσει; Μια χαρά φαίνεται.&lt;/p&gt;</description></item><item><title>Ασύγχρονο Retry Function</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67309.aspx</link><pubDate>Fri, 16 Sep 2011 00:01:38 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67309</guid><dc:creator>Παναγιώτης Καναβός</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67309.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67309</wfw:commentRss><description>Αυτό τον καιρό δουλεύω με ένα Rest API και θέλω να κάνω Retry αν κάποια κλήση αποτυγχάνει για ένα ορισμένο αριθμό επαναλήψεων. Βρήκα &lt;a href="http://stackoverflow.com/questions/6090026/how-to-implement-retry-logic-with-task-parallel-librarytpl"&gt;μία συζήτηση στο StackOverflow&lt;/a&gt; όπου ο Jon Skeet προτείνει τον παρακάτω κώδικα:&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; Func&amp;lt;T&amp;gt; Retry(Func&amp;lt;T&amp;gt; original, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; retryCount)
{
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; () =&amp;gt;
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;while&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;true&lt;/span&gt;)
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;try&lt;/span&gt;
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; original();
            }
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;catch&lt;/span&gt; (Exception e)
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (retryCount == 0)
                {
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;throw&lt;/span&gt;;
                }
                &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;// TODO: Logging&lt;/span&gt;
                retryCount--;
            }
        }
    };
}&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Έτσι μπορώ π.χ. να καλέσω την DowloadString του WebClient 5 φορές:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;var func &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; Retry(() =&amp;gt;
	&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;base&lt;/span&gt;.DownloadString(address), 
	5);
	
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; func();&lt;/span&gt;&lt;/pre&gt;Φυσικά ο πραγματικός κώδικας δεν είναι τόσο απλός καθώς πρέπει να ελέγξω για τα κατάλληλα WebExceptions και να κάνω retry μόνο αν πρόκειται για timeout, αλλά η γενική ιδέα είναι ότι με αυτό τον τρόπο φτιάχνω εύκολα ένα function που κάνει retry.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Ο κώδικας αυτός όμως τρέχει σε ένα thread κι εγώ θα ήθελα (όπως και αυτός που κάνει την αρχική ερώτηση) κάθε επανάληψη να τρέχει σε διαφορετικό thread επειδή τα Rest calls κρατάνε πολύ, ειδικά αν συμβεί timeout. Μία ιδέα θα ήταν να φτιάξω ένα Task για κάθε επανάληψη και να περιμένω με τη Wait για το αποτέλεσμα. Αυτό όμως σημαίνει ότι το thread που καλεί τη Retry θα πρέπει να περιμένει κάθε φορά που εκτελείται η επανάληψη. Ο κώδικας θα είναι κάπως έτσι:&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; Func&amp;lt;T&amp;gt; Retry&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; original, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; retryCount)
{
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; () =&amp;gt;
        {                
        &lt;span class="Apple-tab-span" style="white-space:pre;"&gt;	&lt;/span&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;while&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;true&lt;/span&gt;)
                {
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;try&lt;/span&gt;
                    {
                        var task &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; Task.Factory.StartNew(original);
                        task.Wait();
                        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; task.Result;
                    }
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;catch&lt;/span&gt;&lt;/span&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt; (Exception e)
                    {
&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;"&gt;                        retryCount--;   
&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;"&gt;                    }
&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;"&gt;                }
&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;"&gt;&lt;span class="Apple-tab-span" style="white-space:pre;"&gt;	&lt;/span&gt;};
&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family:'Courier New';font-size:11px;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Ο κώδικας αυτός δεν μου αρέσει και πολύ και θα προτιμούσα κάτι που δεν χρειάζεται Wait για να δουλέψει. Σκέφτεται κανείς κάποιο καλύτερο τρόπο ?&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;</description></item></channel></rss>