<?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>Το SQLite, ένα Job Queue, η F# και οι Agents και πως φτιάχνουμε τη Scan?</title><link>https://www.dotnetzone.gr:443/cs/forums/thread/67620.aspx</link><pubDate>Tue, 04 Oct 2011 17:19:04 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:67620</guid><dc:creator>Παναγιώτης Καναβός</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/forums/thread/67620.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/forums/commentrss.aspx?SectionID=14&amp;PostID=67620</wfw:commentRss><description>Χρησιμοποιώ το &lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; μέσω &lt;a href="http://www.castleproject.org/activerecord/"&gt;Castle.ActiveRecord&lt;/a&gt; ως ultra-lightweight embedded βάση σε μία dropbox-οειδή εφαρμογή και συνάντησα ένα ενδιαφέρον πρόβλημα. Το SQLite κλειδώνει ολόκληρο το αρχείο, δηλαδή ολόκληρη τη βάση, όταν κάποιος γράφει. Επιπλέον, αντί να μπλοκάρει η εγγραφή μέχρι να ελευθερωθεί, ρίχνει exception (αυτό βέβαια μπορεί να είναι πρόβλημα του driver ή του Castle.ActiveRecord). Ακόμα και αν δεν έριχνε exception όμως η καθυστέρηση που θα προκαλούσε στα x threads που ήθελαν να γράψουν θα ήταν καταστροφική.&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Σκέφτηκα αρχικά να φτιάξω ένα Job Queue, μετά από όλες τις συζητήσεις που έχουν γίνει πρόσφατα για functions, lambdas, γιατί το Sharepoint δέχεται lambdas αντί για ονόματα properties. Έφτιαξα λοιπόν ένα&lt;a href="http://msdn.microsoft.com/en-us/library/dd267312.aspx"&gt; BlockingCollection&amp;lt;Action&amp;gt;&lt;/a&gt; στο οποίο από τη μία πλευρά βάζω lambdas για εκτέλεση και από την άλλη έχω ένα thread το οποίο τραβάει τα actions ένα-ένα και τα εκτελεί. Το JobQueue είναι εντελώς γενικό, απλά το χρησιμοποίησα καταρχήν για να εκτελώ db actions:&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;class&lt;/span&gt; JobQueue
    {
        &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;readonly&lt;/span&gt; BlockingCollection&amp;lt;Action&amp;gt; _actionQueue &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; BlockingCollection&amp;lt;Action&amp;gt;();
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; CancellationToken _cancellationToken;
        

        &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;void&lt;/span&gt; Start(CancellationToken token)
        {
            _cancellationToken &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; token;
            Task.Factory.StartNew(ProcessActions, _cancellationToken);
        }

        &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;void&lt;/span&gt; ProcessActions()
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (var action &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; _actionQueue.GetConsumingEnumerable())
            {
                action();
            }
        }

        &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;void&lt;/span&gt; Add(Action action)
        {
            _actionQueue.Add(action);
        }

        &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;void&lt;/span&gt; Stop()
        {
            _actionQueue.CompleteAdding();
        }
       
    }   &lt;/span&gt;&lt;/pre&gt;Και η η προσθήκη ενός νέου action γίνεται ως εξής:&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;myJobQueue.Post(() =&amp;gt;
{
        var filePath &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; path.ToLower();
        var state &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; FileState.Queryable.First(s=&amp;gt; s.FilePath == filePath);
        state.Status=FileStatus.Pending;
        state.Save();
});&lt;/span&gt;&lt;/pre&gt;Έτσι μπορώ να εκτελέσω άμεσα και ασύγχρονα όλα τα db actions, ενώ είμαι σίγουρος ότι θα εκτελεστούν ένα τη φορά με τη σειρά που τα πρόσθεσα.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Μετά όμως άρχισε η κουβέντα με το ασύγχρονο Retry και τα ασύγχρονα Sockets και ο Παλλαδινός με έπρηξε να μου μιλάει συνέχεια για τα agents της F#. Όποιος ασχολείται με Scala θα τα ξέρει ως actors. Στην ουσία είναι ο παρακάτω εξής απλός κώδικας:&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;type Agent&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; MailboxProcessor&amp;lt;'T&amp;gt;
 
let agent &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt;
   Agent.Start(fun inbox -&amp;gt;
     async { &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;do&lt;/span&gt;
               let! msg &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; inbox.Receive()
               printfn &lt;span style="color:#666666;background-color:#e4e4e4;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;"got message '%s'"&lt;/span&gt; msg } )&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Κάνουμε post τα μηνύματα που θέλουμε να εκτελεστούν στον agent και αυτός τα τραβάει σε ένα ξεχωριστό thread και τα εκτελεί.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Η ιδέα μου φάνηκε πολύ πιο απλή και γενική από το Job Queue και έτσι δοκίμασα να φτιάξω κι εγώ κάτι αντίστοιχο σε C#. Η κλάση είναι η παρακάτω:&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;class&lt;/span&gt; Agent&amp;lt;TMessage&amp;gt; : IDisposable
    {
        &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;readonly&lt;/span&gt; BlockingCollection&amp;lt;TMessage&amp;gt; _messages &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; BlockingCollection&amp;lt;TMessage&amp;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;readonly&lt;/span&gt; CancellationTokenSource _cancelSource &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; CancellationTokenSource();
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; CancellationToken CancellationToken;

        &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;readonly&lt;/span&gt; Action&amp;lt;Agent&amp;lt;TMessage&amp;gt;&amp;gt; _process;


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; Agent(Action&amp;lt;Agent&amp;lt;TMessage&amp;gt;&amp;gt; action)
        {
            _process &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; action;
            CancellationToken &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; _cancelSource.Token;
        }

        &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;void&lt;/span&gt; Post(TMessage message)
        {
            _messages.Add(message);
        }

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; Task&amp;lt;TMessage&amp;gt; Receive(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; timeout &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;return&lt;/span&gt; Task&amp;lt;TMessage&amp;gt;.Factory.StartNew(() =&amp;gt;
            {
                TMessage item;
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (!_messages.TryTake(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;out&lt;/span&gt; item, timeout, CancellationToken))
                    &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:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; TimeoutException();
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; item;
            });
        }

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; Task&amp;lt;TMessage&amp;gt; TryReceive(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; timeout &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;return&lt;/span&gt; Task&amp;lt;TMessage&amp;gt;.Factory.StartNew(() =&amp;gt;
            {
                TMessage item;
                _messages.TryTake(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;out&lt;/span&gt; item, timeout, CancellationToken);
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; item;
            });
        }




        &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;void&lt;/span&gt; Start()
        {
            Task.Factory.StartNew(() =&amp;gt; _process(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;), CancellationToken);
        }



        &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; Agent&amp;lt;TMessage&amp;gt; Start(Action&amp;lt;Agent&amp;lt;TMessage&amp;gt;&amp;gt; action)
        {
            var agent &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; Agent&amp;lt;TMessage&amp;gt;(action);
            agent.Start();
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; agent;
        }

        &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;void&lt;/span&gt; Stop()
        {
            _messages.CompleteAdding();
            _cancelSource.Cancel();
        }

        &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;void&lt;/span&gt; DoAsync(Action action)
        {
            Task.Factory.StartNew(action, CancellationToken);
        }


        ~Agent()
        {
            Dispose(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;false&lt;/span&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;void&lt;/span&gt; Dispose()
        {
            Dispose(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;true&lt;/span&gt;);
            GC.SuppressFinalize(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;);
        }

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Dispose(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; disposing)
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (disposing)
            {
                Stop();
                _messages.Dispose();
                _cancelSource.Dispose();
            }
        }

        &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;void&lt;/span&gt; AddFromEnumerable(IEnumerable&amp;lt;TMessage&amp;gt; enumerable)
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (var message &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; enumerable)
            {
                Post(message);
            }
        }

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; IEnumerable&amp;lt;TMessage&amp;gt; GetEnumerable()
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; _messages;
        }
    }&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Η δημιουργία ενός νέου agent γίνεται ως εξής:&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;_agent &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; Agent&amp;lt;MyMessage&amp;gt;.Start(inbox =&amp;gt;
            {
                &lt;/span&gt;&lt;span style="color:black;background-color:transparent;font-family:'Courier New';"&gt;&lt;b&gt;&lt;font class="Apple-style-span" size="2"&gt;Action loop &lt;span style="color:red;background-color:transparent;font-family:'Courier New';"&gt;=&lt;/span&gt; &lt;span style="color:blue;background-color:transparent;font-family:'Courier New';"&gt;null&lt;/span&gt;;
                loop&lt;/font&gt;&lt;/b&gt;&lt;b style="font-size:11px;"&gt; &lt;/b&gt;&lt;span style="color:red;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size:11px;"&gt; () =&amp;gt;
                {
                    &lt;/span&gt;&lt;b&gt;&lt;font class="Apple-style-span" size="2"&gt;var messageTask&lt;/font&gt;&lt;span class="Apple-style-span" style="font-size:11px;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;span style="color:red;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size:11px;"&gt; inbox.Receive();
                    var process &lt;/span&gt;&lt;span style="color:red;background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size:11px;"&gt; &lt;/span&gt;&lt;b&gt;&lt;font class="Apple-style-span" size="2"&gt;messageTask.ContinueWith&lt;/font&gt;&lt;/b&gt;&lt;span class="Apple-style-span" style="font-size:11px;"&gt;(t =&amp;gt;
                    {
                        &lt;/span&gt;&lt;font class="Apple-style-span" size="2"&gt;&lt;b&gt;var message &lt;/b&gt;&lt;span style="color:red;background-color:transparent;font-family:'Courier New';"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/span&gt;&lt;b&gt; t.Result;&lt;/b&gt;&lt;/font&gt;&lt;span class="Apple-style-span" style="font-size:11px;"&gt;
                        &lt;/span&gt;&lt;/span&gt;&lt;span style="background-color:transparent;font-family:'Courier New';font-size:11px;font-weight:normal;"&gt;&lt;font class="Apple-style-span" color="#006400"&gt;//Do stuff with my message here&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;
                        inbox.&lt;/span&gt;&lt;span style="color:black;background-color:transparent;font-family:'Courier New';"&gt;&lt;b&gt;&lt;font class="Apple-style-span" size="2"&gt;DoAsync&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;(loop);
                    });
                };
                loop();
            });&lt;/span&gt;&lt;/pre&gt;ενώ η κλήση γίνεται με ένα απλό _agent.Post(someMessage);&lt;/div&gt;&lt;div&gt;Προφανώς το TMessage μπορεί να είναι οτιδήποτε, ένα data structure ή ένα Action. Το ωραίο είναι ότι μπορώ να δημιουργήσω ένα agent πολύ εύκολα ακριβώς στο σημείο που τον χρειάζομαι, και να του πω ακριβώς πως θέλω να επεξεργαστεί τα μηνύματα. Με το JobQueue ήμουν περιορισμένος σε ένα είδος υλοποίησης και μόνο.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Από την άλλη, η σύνταξη που αναγκάστηκα να χρησιμοποιήσω είναι αρκετά πιο στριφνή σε σχέση με την F#. Ο κώδικας με τα bold δείχνει το "θόρυβο" που αναγκάστηκα να προσθέσω για να έχω το αποτέλεσμα που θέλω:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Για να μπορέσω να εκτελέσω recursion χρειάστηκε να ορίσω το loop πριν του δώσω τιμή. Διαφορετικά ο compiler αρνείται να χρησιμοποιήσει την loop γιατί θεωρεί ότι είναι undefined.&lt;/li&gt;&lt;li&gt;Ο κώδικας χρησιμοποιεί tasks με αποτέλεσμα να γεμίζει ContinueWith και t.Result τα οποία κάνουν τον κώδικα πιο δύσκολο στην ανάγνωση&lt;/li&gt;&lt;li&gt;Η DoAsync κρύβει ένα StartNew που χρησιμοποιεί το CancellationSource ολόκληρου του agent. Αυτό γίνεται γιατί θέλω να σταματήσει η επεργασία τόσο των μηνυμάτων όσο και του loop όταν κάνω Stop.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Φυσικά τα πράγματα θα γίνουν πολύ ευκολότερα με την C# 5 και τα async, await keywords. Ο θόρυβος προστέθηκε γιατί είμαι αναγκασμένος να χειριστώ τα tasks και το cancellation με το χέρι, ενώ η C# θα τα αναλάβει "μαγικά" όπως κάνει τώρα και η F#.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Ακόμα δεν έχω υλοποιήσει όλες τις μεθόδους του &lt;a href="http://msdn.microsoft.com/en-us/library/ee370357.aspx"&gt;MailBoxProcessor&lt;/a&gt;, της κλάσης στην οποία βασίζονται οι F# agents. Συγκεκριμένα, η χρήση BlockingCollection σημαίνει ότι δεν μπορώ να υλοποιήσω εύκολα την Scan. Κανένα από τα concurrent collections δεν περιέχει κάποιο Remove function, ενώ η Scan αφαιρεί από το queue τα μηνύματα που βρίσκει.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Καμμία ιδέα για να βοηθήσει κανείς?&lt;/div&gt;</description></item></channel></rss>